Your IP : 216.73.216.61


Current Path : /home/wuectly/www/03cbe/
Upload File :
Current File : /home/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.php000060400000011622152453734450011413 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-14
 * @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');
	}

	return false;
}

// Load Utilities
JLoader::registerPrefix('icagenda', JPATH_ADMINISTRATOR . '/components/com_icagenda/utilities');

// Test if translation is missing, set to en-GB by default
$language = JFactory::getLanguage();
$language->load('com_icagenda', JPATH_SITE, 'en-GB', true);
$language->load('com_icagenda', JPATH_SITE, null, true);

// Set Input J3
// not in use, because of known issues with JInput and Magic Quotes (Deprecated in PHP 5.3.0 and removed in PHP 5.4.0).
$iCinput = $app->input;

// 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-front.css)
JHtml::stylesheet( 'com_icagenda/icagenda-front.css', false, true );
JHtml::stylesheet( 'com_icagenda/tipTip.css', false, true );

// Set iCtip
$iCtip	 = array();
$iCtip[] = '	jQuery(document).ready(function(){';
$iCtip[] = '		jQuery(".iCtip").tipTip({maxWidth: "200", defaultPosition: "top", edgeOffset: 1});';
$iCtip[] = '	});';

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

// Require the base controller
require_once( JPATH_COMPONENT.'/controller.php' );

// Require specific controller if requested
if ( $controller = JRequest::getVar( 'controller' ) )
{
	$path = JPATH_COMPONENT.'/controllers/'.$controller.'.php';
	if ( file_exists( $path ) ) { require_once $path; }
	else { $controller = ''; }
}

// Create the controller
$classname	= 'icagendaController'.ucfirst($controller);
$controller	= new $classname( );

// Perform the Requested task
$controller->execute( JRequest::getVar( 'task' ) );

// Redirect if set by the controller
$controller->redirect();
com_icagenda/index.html000060400000000054152453734450011141 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_icagenda/views/index.html000060400000000054152453734450012276 0ustar00<html><body bgcolor="#FFFFFF"></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.html000060400000000054152453734450012603 0ustar00<html><body bgcolor="#FFFFFF"></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.php000060400000003560152453734450012045 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-11
 * @since       1.0
 *------------------------------------------------------------------------------
*/

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

require_once(JPATH_COMPONENT_SITE . '/helpers/iCicons.class.php');

/**
 * Controller class for iCagenda.
 */
class iCagendaController extends JControllerLegacy
{
	public function display($cachable = false, $urlparams = false)
	{
//		$cachable = true;

		$paramsC 	= JComponentHelper::getParams('com_icagenda');
		$cache 		= $paramsC->get('enable_cache', 0);
		$cachable 	= false;

		if ($cache == 1)
		{
			$cachable 	= true;
		}

		$document = JFactory::getDocument();

		$safeurlparams = array(
			'catid' => 'INT',
			'id' => 'INT',
			'cid' => 'ARRAY',
			'year' => 'INT',
			'month' => 'INT',
			'limit' => 'UINT',
			'limitstart' => 'UINT',
			'showall' => 'INT',
			'return' => 'BASE64',
			'filter' => 'STRING',
			'filter_order' => 'CMD',
			'filter_order_Dir' => 'CMD',
			'filter-search' => 'STRING',
			'print' => 'BOOLEAN',
			'lang' => 'CMD',
			'Itemid' => 'INT');

		parent::display($cachable, $safeurlparams);

		return $this;
	}

	public function payment()
	{

// Set base path
JLayoutHelper::$defaultBasePath = JPATH_PLUGINS . '/content/ic_paypal/layouts';

// Render mylayout.php
$renderedLayout = JLayoutHelper::render('payment_test');
echo $renderedLayout;
	}
}
com_icagenda/models/events.php000060400000025175152453734450012457 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-14
 * @since       3.4.0
 *------------------------------------------------------------------------------
*/

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

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

/**
 * This models supports retrieving lists of events.
 */
class iCagendaModelEvents 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', 'e.id',
				'ordering', 'e.ordering',
				'state', 'e.state',
				'access', 'e.access', 'access_level',
				'approval', 'e.approval',
				'created', 'e.created',
				'title', 'e.title',
				'username', 'e.username',
				'email', 'e.email',
				'category', 'e.category',
				'cat_color', 'e.catcolor',
				'image', 'e.image',
				'file', 'e.file',
				'next', 'e.next',
				'place', 'e.place',
				'city', 'e.city',
				'country', 'e.country',
				'desc', 'e.desc',
				'language', 'e.language',
				'location', 'e.location',
				'category_id',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to auto-populate the model state.
	 *
	 * Note. Calling getState in this method will result in recursion.
	 * NOT IN USE CURRENTLY
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		// Initialise variables.
		$app = JFactory::getApplication();

		// 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);

		// Load the filter access.
		$access = $app->getUserStateFromRequest($this->context.'.filter.access', 'filter_access', '', 'string');
		$this->setState('filter.access', $access);

		// Load the filter language.
		$language = $app->getUserStateFromRequest($this->context.'.filter.language', 'filter_language', '', 'string');
		$this->setState('filter.language', $language);

		// Filter (dropdown) category
		$category = $this->getUserStateFromRequest($this->context.'.filter.category', 'filter_category');
//		$category = $app->input->get('filter_category');
		$this->setState('filter.category', $category);

		// Filter (dropdown) year
		$year = $this->getUserStateFromRequest($this->context.'.filter.year', 'filter_year', '', 'string');
		$this->setState('filter.year', $year);

		// 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);

		// Load the parameters.
		$params = $app->getParams();
		$this->setState('params', $params);

		// List state information.
		parent::populateState('e.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	3.4.0
	 */
	protected function getStoreId($id = '')
	{
		// Compile the store id.
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.state');
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.language');
		$id .= ':' . $this->getState('filter.category');
		$id .= ':' . $this->getState('filter.year');
//		$id .= ':' . $this->getState('filter.category_id.include');
		$id .= ':' . serialize($this->getState('filter.category_id'));

		return parent::getStoreId($id);
	}

	/**
	 * Build an SQL query to load the list data.
	 *
	 * @return	JDatabaseQuery
	 * @since	3.4.0
	 */
	protected function getListQuery()
	{
		// Get the current user for authorisation checks
		$user	= JFactory::getUser();

		// 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',
				'e.*'
			)
		);
		$query->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.id AS cat_id, c.title AS cat_title, c.color AS cat_color, c.desc AS cat_desc,
						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');

		// 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');

		// Join Total of registrations
		$query->select('r.count AS registered');
		$sub_query = $db->getQuery(true);
		$sub_query->select('r.state, r.date, r.eventid, sum(r.people) AS count');
		$sub_query->from('`#__icagenda_registration` AS r');
		$sub_query->where('r.state > 0');
		$sub_query->group('r.date, r.eventid');
		$query->leftJoin('(' . (string) $sub_query . ') AS r ON ((e.next = r.date OR r.date = "") AND e.id = r.eventid)');

		// 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
		$published = $this->getState('filter.state');

		if (is_numeric($published))
		{
			$query->where('e.state = '.(int) $published);
		}
		elseif ($published === '')
		{
			$query->where('(e.state IN (0, 1))');
		}

		$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))
		{
			$query->where('e.approval <> 1');
		}
		else
		{
			$query->where('e.approval < 2');
		}

		// Filter by access level.
		$access = $this->getState('filter.access');

		if ( ! empty($access)
			&& ! in_array('8', $userGroups))
		{
			$access_levels = implode(',', $user->getAuthorisedViewLevels());

			$query->where('e.access IN (' . $access_levels . ')');
//				->where('c.access IN (' . $access_levels . ')'); // To be added later, when access integrated to category
		}

		// Filter by language
		if ($this->getState('filter.language'))
		{
			$query->where('e.language in (' . $db->q(JFactory::getLanguage()->getTag()) . ',' . $db->q('*') . ')');
		}

		// Filter by search in title
//		$search = $this->getState('filter.search');

//		if (!empty($search))
//		{
//			if (stripos($search, 'id:') === 0)
//			{
//				$query->where('e.id = '.(int) substr($search, 3));
//			}
//			else
//			{
//				$search = $db->Quote('%'.$db->escape($search, true).'%');
//				$query->where('( e.title LIKE '.$search.' OR e.username LIKE '.$search.' OR e.id LIKE '.$search.' OR e.email LIKE '.$search.' OR e.file LIKE '.$search.' OR e.place LIKE '.$search.' OR e.city LIKE '.$search.' OR e.country LIKE '.$search.' OR e.desc LIKE '.$search.' OR c.title LIKE '.$search.')');
//			}
//		}

		// Filter by categories.
		$categoryId = $this->getState('filter.category_id');

		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 . ')');
		}

		// Filter by Dates
		$dates_filter = $this->getState('filter.upcoming', '0');

		// 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');

		$all_dates_with_id	= icagendaEventsData::getAllDates($dates_filter, '2', $this->state->get('list.direction'), 'no');

		$dpp_array = $dpp_dates = array();

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

		$list_id = implode(', ', $dpp_array);

		if (count($dpp_array))
		{
			$query->where('e.id IN (' . $list_id . ')');
		}
		else
		{
			return false;
		}

		// 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;
	}

	/**
	 * Method to get an array of data items.
	 *
	 * @return  mixed  An array of data items on success, false on failure.
	 *
	 * @since   12.2
	 */
	public function getItems()
	{
		if ($items = parent::getItems())
		{
			//Do any procesing on fields here if needed
//			foreach ($items AS $item)
//			{
//				$item->loadEventCustomFields	= icagendaEventData::loadEventCustomFields($item->id);
//				$item->registeredUsers			= icagendaRegistrationParticipants::registeredUsers($item);
//			}
		}

		return $items;
	}
}
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.html000060400000000054152453734450013552 0ustar00<html><body bgcolor="#FFFFFF"></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.xml000060400000000712152453734450015012 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_icagenda/models/fields" >
		<field
			name="captcha"
			type="captcha"
			label="COM_ICAGENDA_CAPTCHA_LABEL"
			description="COM_ICAGENDA_CAPTCHA_DESC"
			validate="captcha"
			namespace="registration"
		/>
		<field
			name="date"
			type="calendar"
			label="COM_ICAGENDA_CAPTCHA_LABEL"
			description="COM_ICAGENDA_CAPTCHA_DESC"
		/>
	</fieldset>
</form>
com_icagenda/models/index.html000060400000000054152453734450012424 0ustar00<html><body bgcolor="#FFFFFF"></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.php000060400000003711152453734450012676 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.application.component.model' );

/**
 * iCagenda Model
 */

class iCagendaModelicagenda extends JModelItem
{
	function getText()
	{
		$db =& JFactory::getDBO();
		$query = 'SELECT * FROM #__icagenda';
		$db->setQuery( $query );
		$value =& $db->loadObjectList();
		return $value;
	}
	/**
	 * @var object item
	 */
	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	2.5
	 */
	protected function populateState() 
	{
		$app = JFactory::getApplication();
		// Get the message id
		$id = JRequest::getInt('id');
		$this->setState('message.id', $id);
 

		// Load the parameters.
		$params = $app->getParams();
		$this->setState('params', $params);
		parent::populateState();
	}
 
	/**
	 * 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	2.5
	 */
	public function getTable($type = 'iCagenda', $prefix = 'iCagendaTable', $config = array()) 
	{
		return JTable::getInstance($type, $prefix, $config);
	}
 
}com_menus/menus.php000060400000001455152453734450010406 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

// Load the required admin language files
$lang   = JFactory::getLanguage();
$app    = JFactory::getApplication();

if ($app->input->get('view') === 'items' && $app->input->get('layout') === 'modal')
{
	if (!JFactory::getUser()->authorise('core.create', 'com_menus'))
	{
		$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');

		return;
	}
}

$lang->load('com_menus', JPATH_ADMINISTRATOR);

// Trigger the controller
$controller = JControllerLegacy::getInstance('Menus');
$controller->execute($app->input->get('task'));
$controller->redirect();
com_menus/controller.php000060400000002124152453734450011434 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

/**
 * Menus manager master display controller.
 *
 * @since  3.7.0
 */
class MenusController extends JControllerLegacy
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *                          Recognized key values include 'name', 'default_task', 'model_path', and
	 *                          'view_path' (this list is not meant to be comprehensive).
	 *
	 * @since   3.7.0
	 */
	public function __construct($config = array())
	{
		$this->input = JFactory::getApplication()->input;

		// Menus frontpage Editor Menu proxying:
		if ($this->input->get('view') === 'items' && $this->input->get('layout') === 'modal')
		{
			JHtml::_('stylesheet', 'system/adminlist.css', array(), true);
			$config['base_path'] = JPATH_COMPONENT_ADMINISTRATOR;
		}

		parent::__construct($config);
	}
}
com_menus/models/forms/filter_items.xml000060400000007157152453734450014374 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_menus/models/fields" />
		<field
			name="menutype"
			type="menu"
			label="COM_MENUS_SELECT_MENU_FILTER"
			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"
			/>
			<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"
				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.php000060400000023053152453734450012711 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\Registry\Registry;

/**
 * HTML View class for the Tags component
 *
 * @since  3.1
 */
class TagsViewTag extends JViewLegacy
{
	/**
	 * The model state
	 *
	 * @var    \Joomla\Registry\Registry
	 * @since  3.1
	 */
	protected $state;

	/**
	 * An array of items.
	 *
	 * @var    array
	 * @since  3.1
	 */
	protected $items;

	/**
	 * The active JObject (on success, false on failure)
	 *
	 * @var    JObject|boolean
	 * @since  3.1
	 */
	protected $item;

	/**
	 * Array of Children objects
	 *
	 * @var    array
	 * @since  3.1
	 */
	protected $children;

	/**
	 * The pagination object.
	 *
	 * @var    JPagination
	 * @since  3.1
	 */
	protected $pagination;

	/**
	 * The application parameters
	 *
	 * @var    \Joomla\Registry\Registry  The parameters object
	 * @since  3.1
	 */
	protected $params;

	/**
	 * Array of tags title
	 *
	 * @var    array
	 * @since  3.1
	 */
	protected $tags_title;

	/**
	 * 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.1
	 */
	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');
		$item       = $this->get('Item');
		$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 whether access level allows access.
		// @TODO: Should already be computed in $item->params->get('access-view')
		$user   = JFactory::getUser();
		$groups = $user->getAuthorisedViewLevels();

		foreach ($item as $itemElement)
		{
			if (!in_array($itemElement->access, $groups))
			{
				unset($itemElement);
			}

			// Prepare the data.
			if (!empty($itemElement))
			{
				$temp = new Registry($itemElement->params);
				$itemElement->params   = clone $params;
				$itemElement->params->merge($temp);
				$itemElement->params   = (array) json_decode($itemElement->params);
				$itemElement->metadata = new Registry($itemElement->metadata);
			}
		}

		if ($items !== false)
		{
			JPluginHelper::importPlugin('content');

			foreach ($items as $itemElement)
			{
				$itemElement->event = new stdClass;

				// For some plugins.
				!empty($itemElement->core_body) ? $itemElement->text = $itemElement->core_body : $itemElement->text = null;

				$itemElement->core_params = new Registry($itemElement->core_params);

				$dispatcher = JEventDispatcher::getInstance();

				$dispatcher->trigger('onContentPrepare', array ('com_tags.tag', &$itemElement, &$itemElement->core_params, 0));

				$results = $dispatcher->trigger('onContentAfterTitle', array('com_tags.tag', &$itemElement, &$itemElement->core_params, 0));
				$itemElement->event->afterDisplayTitle = trim(implode("\n", $results));

				$results = $dispatcher->trigger('onContentBeforeDisplay', array('com_tags.tag', &$itemElement, &$itemElement->core_params, 0));
				$itemElement->event->beforeDisplayContent = trim(implode("\n", $results));

				$results = $dispatcher->trigger('onContentAfterDisplay', array('com_tags.tag', &$itemElement, &$itemElement->core_params, 0));
				$itemElement->event->afterDisplayContent = trim(implode("\n", $results));

				// Write the results back into the body
				if (!empty($itemElement->core_body))
				{
					$itemElement->core_body = $itemElement->text;
				}

				// Categories store the images differently so lets re-map it so the display is correct
				if ($itemElement->type_alias === 'com_content.category')
				{
					$itemElement->core_images = json_encode(
						array(
							'image_intro' => $itemElement->core_params->get('image', ''),
							'image_intro_alt' => $itemElement->core_params->get('image_alt', '')
						)
					);
				}
			}
		}

		$this->state      = $state;
		$this->items      = $items;
		$this->children   = $children;
		$this->parent     = $parent;
		$this->pagination = $pagination;
		$this->user       = $user;
		$this->item       = $item;

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', ''));

		// Merge tag params. If this is single-tag view, menu params override tag params
		// Otherwise, article params override menu item params
		$this->params = $this->state->get('params');
		$active       = $app->getMenu()->getActive();
		$temp         = clone $this->params;

		// Convert item params to a Registry object
		$item[0]->params = new Registry($item[0]->params);

		// Check to see which parameters should take priority
		if ($active)
		{
			$currentLink = $active->link;

			// If the current view is the active item and a tag view for one tag, then the menu item params take priority
			if (strpos($currentLink, 'view=tag') && strpos($currentLink, '&id[0]=' . (string) $item[0]->id))
			{
				// $item[0]->params are the tag params, $temp are the menu item params
				// Merge so that the menu item params take priority
				$item[0]->params->merge($temp);

				// Load layout from active query (in case it is an alternative menu item)
				if (isset($active->query['layout']))
				{
					$this->setLayout($active->query['layout']);
				}
			}
			else
			{
				// Current menuitem is not a single tag view, so the tag params take priority.
				// Merge the menu item params with the tag params so that the tag params take priority
				$temp->merge($item[0]->params);
				$item[0]->params = $temp;

				// Check for alternative layouts (since we are not in a single-article menu item)
				// Single-article menu item layout takes priority over alt layout for an article
				if ($layout = $item[0]->params->get('tag_layout'))
				{
					$this->setLayout($layout);
				}
			}
		}
		else
		{
			// Merge so that item params take priority
			$temp->merge($item[0]->params);
			$item[0]->params = $temp;

			// Check for alternative layouts (since we are not in a single-tag menu item)
			// Single-tag menu item layout takes priority over alt layout for an article
			if ($layout = $item[0]->params->get('tag_layout'))
			{
				$this->setLayout($layout);
			}
		}

		// Increment the hit counter
		$model = $this->getModel();
		$model->hit();

		$this->_prepareDocument();

		parent::display($tpl);
	}

	/**
	 * Prepares the document.
	 *
	 * @return  void
	 */
	protected function _prepareDocument()
	{
		$app              = JFactory::getApplication();
		$menu             = $app->getMenu()->getActive();
		$this->tags_title = $this->getTagsTitle();
		$pathway          = $app->getPathway();
		$title            = '';

		// Highest priority for "Browser Page Title".
		if ($menu)
		{
			$title = $menu->params->get('page_title', '');
		}

		if ($this->tags_title)
		{
			$this->params->def('page_heading', $this->tags_title);
			$title = $title ?: $this->tags_title;
		}
		elseif ($menu)
		{
			$this->params->def('page_heading', $this->params->get('page_title', $menu->title));
			$title = $title ?: $this->params->get('page_title', $menu->title);

			if (!isset($menu->query['option']) || $menu->query['option'] !== 'com_tags')
			{
				$this->params->set('page_subheading', $menu->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);

		$pathway->addItem($title);

		foreach ($this->item as $itemElement)
		{
			if ($itemElement->metadesc)
			{
				$this->document->setDescription($itemElement->metadesc);
			}
			elseif ($this->params->get('menu-meta_description'))
			{
				$this->document->setDescription($this->params->get('menu-meta_description'));
			}

			if ($itemElement->metakey)
			{
				$this->document->setMetadata('keywords', $itemElement->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 (count($this->item) === 1)
		{
			foreach ($this->item[0]->metadata->toArray() as $k => $v)
			{
				if ($v)
				{
					$this->document->setMetadata($k, $v);
				}
			}
		}

		if ($this->params->get('show_feed_link', 1) == 1)
		{
			$link    = '&format=feed&limitstart=';
			$attribs = array('type' => 'application/rss+xml', 'title' => 'RSS 2.0');
			$this->document->addHeadLink(JRoute::_($link . '&type=rss'), 'alternate', 'rel', $attribs);
			$attribs = array('type' => 'application/atom+xml', 'title' => 'Atom 1.0');
			$this->document->addHeadLink(JRoute::_($link . '&type=atom'), 'alternate', 'rel', $attribs);
		}
	}

	/**
	 * Creates the tags title for the output
	 *
	 * @return  boolean
	 */
	protected function getTagsTitle()
	{
		$tags_title = array();

		if (!empty($this->item))
		{
			$user   = JFactory::getUser();
			$groups = $user->getAuthorisedViewLevels();

			foreach ($this->item as $item)
			{
				if (in_array($item->access, $groups))
				{
					$tags_title[] = $item->title;
				}
			}
		}

		return implode(' ', $tags_title);
	}
}
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.php000060400000002157152453734450013561 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');
$description      = $this->params->get('all_tags_description');
$descriptionImage = $this->params->get('all_tags_description_image');

?>
<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('all_tags_show_description_image') && !empty($descriptionImage)) : ?>
		<div>
			<img src="<?php echo htmlspecialchars($descriptionImage, ENT_QUOTES, 'UTF-8'); ?>" />
		</div>
	<?php endif; ?>
	<?php if (!empty($description)) : ?>
		<div>
			<?php echo $description; ?>
		</div>
	<?php endif; ?>
	<?php echo $this->loadTemplate('items'); ?>
</div>
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.xml000060400000013141152453734450013565 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_TAGS_TAGS_VIEW_DEFAULT_TITLE" option="COM_TAGS_TAG_VIEW_DEFAULT_OPTION">
		<help
			key="JHELP_MENUS_MENU_ITEM_TAGS_ITEMS_LIST_ALL"
		/>
		<message>
			<![CDATA[COM_TAGS_TAGS_VIEW_DEFAULT_DESC]]>
		</message>
	</layout>
	<!-- Add fields to the request variables for the layout. -->
	<fields name="request">
		<fieldset name="request">

			<field
				name="parent_id"
				type="tag"
				label="COM_TAGS_FIELD_PARENT_TAG_LABEL"
				description="COM_TAGS_FIELD_PARENT_TAG_DESC"
				mode="nested"
				>
				<option value="">JNONE</option>
				<option value="1">JGLOBAL_ROOT</option>
			</field>

			<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">

			<field
				name="tag_columns"
				type="number"
				label="COM_TAGS_COMPACT_COLUMNS_LABEL"
				description="COM_TAGS_NUMBER_COLUMNS_DESC"
				default="4"
				filter="integer"
			/>

			<field
				name="all_tags_description"
				type="textarea"
				label="COM_TAGS_SHOW_ALL_TAGS_DESCRIPTION_LABEL"
				description="COM_TAGS_ALL_TAGS_DESCRIPTION_DESC"
				class="inputbox"
				rows="3"
				cols="30"
				filter="safehtml"
			/>

			<field
				name="all_tags_show_description_image"
				type="list"
				label="COM_TAGS_SHOW_ALL_TAGS_IMAGE_LABEL"
				description="COM_TAGS_SHOW_ALL_TAGS_IMAGE_DESC"
				class="chzn-color"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="all_tags_description_image"
				type="media"
				label="COM_TAGS_ALL_TAGS_MEDIA_LABEL"
				description="COM_TAGS_ALL_TAGS_MEDIA_DESC"
			/>

			<field
				name="all_tags_orderby"
				type="list"
				label="JGLOBAL_FIELD_FIELD_ORDERING_LABEL"
				description="JGLOBAL_FIELD_FIELD_ORDERING_DESC"
				useglobal="true"
				>
				<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="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>

			<field
				name="all_tags_show_tag_image"
				type="list"
				label="COM_TAGS_SHOW_ITEM_IMAGE_LABEL"
				description="COM_TAGS_SHOW_ITEM_IMAGE_DESC"
				useglobal="true"
				class="chzn-color"
				>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</option>
			</field>

			<field
				name="all_tags_show_tag_description"
				type="list"
				label="COM_TAGS_SHOW_ITEM_DESCRIPTION_LABEL"
				description="COM_TAGS_SHOW_ITEM_DESCRIPTION_DESC"
				class="chzn-color"
				>
				<option value="">JGLOBAL_USE_GLOBAL</option>
				<option value="0">JHIDE</option>
				<option value="1">JSHOW</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"
			/>

			<field
				name="all_tags_show_tag_hits"
				type="list"
				label="JGLOBAL_HITS"
				description="COM_TAGS_FIELD_CONFIG_HITS_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_ALL_SELECTION_OPTIONS">

			<field
				name="maximum"
				type="number"
				label="COM_TAGS_LIST_MAX_LABEL"
				description="COM_TAGS_LIST_MAX_DESC"
				default="200"
				filter="integer"
			/>

			<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_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="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/tags/view.html.php000060400000014303152453734450013072 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\Registry\Registry;

/**
 * HTML View class for the Tags component
 *
 * @since  3.1
 */
class TagsViewTags extends JViewLegacy
{
	protected $state;

	protected $items;

	protected $item;

	protected $pagination;

	protected $params;

	/**
	 * 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 some data from the models
		$this->state      = $this->get('State');
		$this->items      = $this->get('Items');
		$this->pagination = $this->get('Pagination');
		$this->params = $this->state->get('params');
		$this->user   = JFactory::getUser();

		// Flag indicates to not add limitstart=0 to URL
		$this->pagination->hideEmptyLimitstart = true;

		/*
		 * // Change to catch
		 * if (count($errors = $this->get('Errors'))) {
		 * JError::raiseError(500, implode("\n", $errors));
		 * return false;
		 */

		// Check whether access level allows access.
		// @todo: Should already be computed in $item->params->get('access-view')
		$groups = $this->user->getAuthorisedViewLevels();

		if (!empty($this->items))
		{
			foreach ($this->items as $itemElement)
			{
				if (!in_array($itemElement->access, $groups))
				{
					unset($itemElement);
				}

				// Prepare the data.
				$temp = new Registry($itemElement->params);
				$itemElement->params = clone $this->params;
				$itemElement->params->merge($temp);
				$itemElement->params = (array) json_decode($itemElement->params);
			}
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($this->params->get('pageclass_sfx', ''));

		$active = JFactory::getApplication()->getMenu()->getActive();

		// Load layout from active query (in case it is an alternative menu item)
		if ($active && isset($active->query['option']) && $active->query['option'] === 'com_tags' && $active->query['view'] === 'tags')
		{
			if (isset($active->query['layout']))
			{
				$this->setLayout($active->query['layout']);
			}
		}
		else
		{
			// Load default All Tags layout from component
			if ($layout = $this->params->get('tags_layout'))
			{
				$this->setLayout($layout);
			}
		}

		$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_TAGS_DEFAULT_PAGE_TITLE'));
		}

		if ($menu && (!isset($menu->query['option']) || $menu->query['option'] !== 'com_tags'))
		{
			$this->params->set('page_subheading', $menu->title);
		}

		// Set metadata for all tags menu item
		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'));
		}

		// If this is not a single tag menu item, set the page title to the tag titles
		$title = '';

		if (!empty($this->item))
		{
			foreach ($this->item as $i => $itemElement)
			{
				if ($itemElement->title)
				{
					if ($i != 0)
					{
						$title .= ', ';
					}

					$title .= $itemElement->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);

			foreach ($this->item as $itemElement)
			{
				if ($itemElement->metadesc)
				{
					$this->document->setDescription($this->item->metadesc);
				}
				elseif ($this->params->get('menu-meta_description'))
				{
					$this->document->setDescription($this->params->get('menu-meta_description'));
				}

				if ($itemElement->metakey)
				{
					$this->document->setMetadata('keywords', $this->tag->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 ($app->get('MetaAuthor') == '1')
				{
					$this->document->setMetaData('author', $itemElement->created_user_id);
				}

				$mdata = $this->item->metadata->toArray();

				foreach ($mdata as $k => $v)
				{
					if ($v)
					{
						$this->document->setMetadata($k, $v);
					}
				}
			}
		}

		// Respect configuration Sitename Before/After for TITLE in views All Tags.
		if (!$title && ($pos = $app->get('sitename_pagetitles', 0)))
		{
			$title = $this->document->getTitle();

			if ($pos == 1)
			{
				$title = JText::sprintf('JPAGETITLE', $app->get('sitename'), $title);
			}
			else
			{
				$title = JText::sprintf('JPAGETITLE', $title, $app->get('sitename'));
			}

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

		// Add alternative feed link
		if ($this->params->get('show_feed_link', 1) == 1)
		{
			$link    = '&format=feed&limitstart=';
			$attribs = array('type' => 'application/rss+xml', 'title' => 'RSS 2.0');
			$this->document->addHeadLink(JRoute::_($link . '&type=rss'), 'alternate', 'rel', $attribs);
			$attribs = array('type' => 'application/atom+xml', 'title' => 'Atom 1.0');
			$this->document->addHeadLink(JRoute::_($link . '&type=atom'), 'alternate', 'rel', $attribs);
		}
	}
}
com_tags/controllers/tags.php000060400000002504152453734450012366 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;

/**
 * The Tags List Controller
 *
 * @since  3.1
 */
class TagsControllerTags extends JControllerLegacy
{
	/**
	 * Method to search tags with AJAX
	 *
	 * @return  void
	 */
	public function searchAjax()
	{
		// Required objects
		$app = JFactory::getApplication();
		$user = JFactory::getUser();

		// Receive request data
		$filters = array(
			'like'      => trim($app->input->get('like', null, 'string')),
			'title'     => trim($app->input->get('title', null, 'string')),
			'flanguage' => $app->input->get('flanguage', null, 'word'),
			'published' => $app->input->get('published', 1, 'int'),
			'parent_id' => $app->input->get('parent_id', 0, 'int'),
			'access'    => $user->getAuthorisedViewLevels(),
		);

		if ((!$user->authorise('core.edit.state', 'com_tags')) && (!$user->authorise('core.edit', 'com_tags')))
		{
			// Filter on published for those who do not have edit or edit.state rights.
			$filters['published'] = 1;
		}

		$results = JHelperTags::searchTags($filters);

		if ($results)
		{
			// Output a JSON object
			echo json_encode($results);
		}

		$app->close();
	}
}
com_tags/models/tag.php000060400000021432152453734450011121 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;

/**
 * Tags Component Tag Model
 *
 * @since  3.1
 */
class TagsModelTag extends JModelList
{
	/**
	 * The tags that apply.
	 *
	 * @var    object
	 * @since  3.1
	 */
	protected $tag = null;

	/**
	 * The list of items associated with the tags.
	 *
	 * @var    array
	 * @since  3.1
	 */
	protected $items = null;

	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *
	 * @see     JController
	 * @since   3.1
	 */
	public function __construct($config = array())
	{
		if (empty($config['filter_fields']))
		{
			$config['filter_fields'] = array(
				'core_content_id', 'c.core_content_id',
				'core_title', 'c.core_title',
				'core_type_alias', 'c.core_type_alias',
				'core_checked_out_user_id', 'c.core_checked_out_user_id',
				'core_checked_out_time', 'c.core_checked_out_time',
				'core_catid', 'c.core_catid',
				'core_state', 'c.core_state',
				'core_access', 'c.core_access',
				'core_created_user_id', 'c.core_created_user_id',
				'core_created_time', 'c.core_created_time',
				'core_modified_time', 'c.core_modified_time',
				'core_ordering', 'c.core_ordering',
				'core_featured', 'c.core_featured',
				'core_language', 'c.core_language',
				'core_hits', 'c.core_hits',
				'core_publish_up', 'c.core_publish_up',
				'core_publish_down', 'c.core_publish_down',
				'core_images', 'c.core_images',
				'core_urls', 'c.core_urls',
				'match_count',
			);
		}

		parent::__construct($config);
	}

	/**
	 * Method to get a list of items for a list of tags.
	 *
	 * @return  mixed  An array of objects on success, false on failure.
	 *
	 * @since   3.1
	 */
	public function getItems()
	{
		// Invoke the parent getItems method to get the main list
		$items = parent::getItems();

		if (!empty($items))
		{
			foreach ($items as $item)
			{
				$item->link = TagsHelperRoute::getItemRoute(
					$item->content_item_id,
					$item->core_alias,
					$item->core_catid,
					$item->core_language,
					$item->type_alias,
					$item->router
				);

				// Get display date
				switch ($this->state->params->get('tag_list_show_date'))
				{
					case 'modified':
						$item->displayDate = $item->core_modified_time;
						break;

					case 'created':
						$item->displayDate = $item->core_created_time;
						break;

					default:
					case 'published':
						$item->displayDate = ($item->core_publish_up == 0) ? $item->core_created_time : $item->core_publish_up;
						break;
				}
			}
		}

		return $items;
	}

	/**
	 * Method to build an SQL query to load the list data of all items with a given tag.
	 *
	 * @return  string  An SQL query
	 *
	 * @since   3.1
	 */
	protected function getListQuery()
	{
		$tagId  = $this->getState('tag.id') ? : '';

		$typesr = $this->getState('tag.typesr');
		$orderByOption = $this->getState('list.ordering', 'c.core_title');
		$includeChildren = $this->state->params->get('include_children', 0);
		$orderDir = $this->getState('list.direction', 'ASC');
		$matchAll = $this->getState('params')->get('return_any_or_all', 1);
		$language = $this->getState('tag.language');
		$stateFilter = $this->getState('tag.state');

		// Optionally filter on language
		if (empty($language))
		{
			$language = JComponentHelper::getParams('com_tags')->get('tag_list_language_filter', 'all');
		}

		$tagsHelper = new JHelperTags;
		$query = $tagsHelper->getTagItemsQuery($tagId, $typesr, $includeChildren, $orderByOption, $orderDir, $matchAll, $language, $stateFilter);

		if ($this->state->get('list.filter'))
		{
			$query->where($this->_db->quoteName('c.core_title') . ' LIKE ' . $this->_db->quote('%' . $this->state->get('list.filter') . '%'));
		}

		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.1
	 */
	protected function populateState($ordering = 'c.core_title', $direction = 'ASC')
	{
		$app = JFactory::getApplication();

		// Load the parameters.
		$params = $app->isClient('administrator') ? JComponentHelper::getParams('com_tags') : $app->getParams();

		$this->setState('params', $params);

		// Load state from the request.
		$ids = (array) $app->input->get('id', array(), 'string');

		if (count($ids) == 1)
		{
			$ids = explode(',', $ids[0]);
		}

		$ids = ArrayHelper::toInteger($ids);

		// Remove zero values resulting from bad input
		$ids = array_filter($ids);

		$pkString = implode(',', $ids);

		$this->setState('tag.id', $pkString);

		// Get the selected list of types from the request. If none are specified all are used.
		$typesr = $app->input->get('types', array(), 'array');

		if ($typesr)
		{
			// Implode is needed because the array can contain a string with a coma separated list of ids
			$typesr = implode(',', $typesr);

			// Sanitise
			$typesr = explode(',', $typesr);
			$typesr = ArrayHelper::toInteger($typesr);

			$this->setState('tag.typesr', $typesr);
		}

		$language = $app->input->getString('tag_list_language_filter');
		$this->setState('tag.language', $language);

		// List state information
		$format = $app->input->getWord('format');

		if ($format === 'feed')
		{
			$limit = $app->get('feed_limit');
		}
		else
		{
			$limit = $params->get('display_num', $app->get('list_limit', 20));
			$limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $limit, 'uint');
		}

		$this->setState('list.limit', $limit);

		$offset = $app->input->get('limitstart', 0, 'uint');
		$this->setState('list.start', $offset);

		$itemid = $pkString . ':' . $app->input->get('Itemid', 0, 'int');
		$orderCol = $app->getUserStateFromRequest('com_tags.tag.list.' . $itemid . '.filter_order', 'filter_order', '', 'string');
		$orderCol = !$orderCol ? $this->state->params->get('tag_list_orderby', 'c.core_title') : $orderCol;

		if (!in_array($orderCol, $this->filter_fields))
		{
			$orderCol = 'c.core_title';
		}

		$this->setState('list.ordering', $orderCol);

		$listOrder = $app->getUserStateFromRequest('com_tags.tag.list.' . $itemid . '.filter_order_direction', 'filter_order_Dir', '', 'string');
		$listOrder = !$listOrder ? $this->state->params->get('tag_list_orderby_direction', 'ASC') : $listOrder;

		if (!in_array(strtoupper($listOrder), array('ASC', 'DESC', '')))
		{
			$listOrder = 'ASC';
		}

		$this->setState('list.direction', $listOrder);

		$this->setState('tag.state', 1);

		// Optional filter text
		$filterSearch = $app->getUserStateFromRequest('com_tags.tag.list.' . $itemid . '.filter_search', 'filter-search', '', 'string');
		$this->setState('list.filter', $filterSearch);
	}

	/**
	 * Method to get tag data for the current tag or tags
	 *
	 * @param   integer  $pk  An optional ID
	 *
	 * @return  object
	 *
	 * @since   3.1
	 */
	public function getItem($pk = null)
	{
		if (!isset($this->item))
		{
			$this->item = false;

			if (empty($pk))
			{
				$pk = $this->getState('tag.id');
			}

			// Get a level row instance.
			$table = JTable::getInstance('Tag', 'TagsTable');

			$idsArray = explode(',', $pk);

			// Attempt to load the rows into an array.
			foreach ($idsArray as $id)
			{
				try
				{
					$table->load($id);

					// Check published state.
					if ($published = $this->getState('tag.state'))
					{
						if ($table->published != $published)
						{
							continue;
						}
					}

					if (!in_array($table->access, JFactory::getUser()->getAuthorisedViewLevels()))
					{
						continue;
					}

					// Convert the JTable to a clean JObject.
					$properties = $table->getProperties(1);
					$this->item[] = ArrayHelper::toObject($properties, 'JObject');
				}
				catch (RuntimeException $e)
				{
					$this->setError($e->getMessage());

					return false;
				}
			}
		}

		if (!$this->item)
		{
			return JError::raiseError(404, JText::_('COM_TAGS_TAG_NOT_FOUND'));
		}

		return $this->item;
	}

	/**
	 * Increment the hit counter.
	 *
	 * @param   integer  $pk  Optional primary key of the article 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('tag.id');
			$table = JTable::getInstance('Tag', 'TagsTable');
			$table->hit($pk);

			// Load the table data for later
			$table->load($pk);

			if (!$table->hasPrimaryKey())
			{
				JError::raiseError(404, JText::_('COM_TAGS_TAG_NOT_FOUND'));
			}
		}

		return true;
	}
}
com_tags/models/tags.php000060400000010676152453734450011314 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\Registry\Registry;

/**
 * This models supports retrieving a list of tags.
 *
 * @since  3.1
 */
class TagsModelTags extends JModelList
{
	/**
	 * Model context string.
	 *
	 * @var    string
	 * @since  3.1
	 */
	public $_context = 'com_tags.tags';

	/**
	 * 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   3.1
	 */
	protected function populateState($ordering = null, $direction = null)
	{
		$app = JFactory::getApplication('site');

		// Load state from the request.
		$pid = $app->input->getInt('parent_id');
		$this->setState('tag.parent_id', $pid);

		$language = $app->input->getString('tag_list_language_filter');
		$this->setState('tag.language', $language);

		$offset = $app->input->get('limitstart', 0, 'uint');
		$this->setState('list.offset', $offset);
		$app = JFactory::getApplication();

		$params = $app->getParams();
		$this->setState('params', $params);

		$this->setState('list.limit', $params->get('maximum', 200));

		$this->setState('filter.published', 1);
		$this->setState('filter.access', true);

		$user = JFactory::getUser();

		if ((!$user->authorise('core.edit.state', 'com_tags')) &&  (!$user->authorise('core.edit', 'com_tags')))
		{
			$this->setState('filter.published', 1);
		}

		// Optional filter text
		$itemid = $pid . ':' . $app->input->getInt('Itemid', 0);
		$filterSearch = $app->getUserStateFromRequest('com_tags.tags.list.' . $itemid . '.filter_search', 'filter-search', '', 'string');
		$this->setState('list.filter', $filterSearch);
	}

	/**
	 * Method to build an SQL query to load the list data.
	 *
	 * @return  string  An SQL query
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		$app            = JFactory::getApplication('site');
		$user           = JFactory::getUser();
		$groups         = implode(',', $user->getAuthorisedViewLevels());
		$pid            = $this->getState('tag.parent_id');
		$orderby        = $this->state->params->get('all_tags_orderby', 'title');
		$published      = $this->state->params->get('published', 1);
		$orderDirection = $this->state->params->get('all_tags_orderby_direction', 'ASC');
		$language       = $this->getState('tag.language');

		// Create a new query object.
		$db    = $this->getDbo();
		$query = $db->getQuery(true);

		// Select required fields from the tags.
		$query->select('a.*, u.name as created_by_user_name, u.email')
			->from($db->quoteName('#__tags') . ' AS a')
			->join('LEFT', '#__users AS u ON a.created_user_id = u.id')
			->where($db->quoteName('a.access') . ' IN (' . $groups . ')');

		if (!empty($pid))
		{
			$query->where($db->quoteName('a.parent_id') . ' = ' . $pid);
		}

		// Exclude the root.
		$query->where($db->quoteName('a.parent_id') . ' <> 0');

		// Optionally filter on language
		if (empty($language))
		{
			$language = JComponentHelper::getParams('com_tags')->get('tag_list_language_filter', 'all');
		}

		if ($language !== 'all')
		{
			if ($language === 'current_language')
			{
				$language = JHelperContent::getCurrentLanguage();
			}

			$query->where($db->quoteName('language') . ' IN (' . $db->quote($language) . ', ' . $db->quote('*') . ')');
		}

		// List state information
		$format = $app->input->getWord('format');

		if ($format === 'feed')
		{
			$limit = $app->get('feed_limit');
		}
		else
		{
			if ($this->state->params->get('show_pagination_limit'))
			{
				$limit = $app->getUserStateFromRequest('global.list.limit', 'limit', $app->get('list_limit'), 'uint');
			}
			else
			{
				$limit = $this->state->params->get('maximum', 20);
			}
		}

		$this->setState('list.limit', $limit);

		$offset = $app->input->get('limitstart', 0, 'uint');
		$this->setState('list.start', $offset);

		// Optionally filter on entered value
		if ($this->state->get('list.filter'))
		{
			$query->where($db->quoteName('a.title') . ' LIKE ' . $db->quote('%' . $this->state->get('list.filter') . '%'));
		}

		$query->where($db->quoteName('a.published') . ' = ' . $published);

		$query->order($db->quoteName($orderby) . ' ' . $orderDirection . ', a.title ASC');

		return $query;
	}
}
com_tags/controller.php000060400000002571152453734450011251 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 Controller
 *
 * @since  3.1
 */
class TagsController extends JControllerLegacy
{
	/**
	 * Method to display a view.
	 *
	 * @param   boolean        $cachable   If true, the view output will be cached
	 * @param   mixed|boolean  $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)
	{
		$user = JFactory::getUser();

		// Set the default view name and format from the Request.
		$vName = $this->input->get('view', 'tags');
		$this->input->set('view', $vName);

		if ($user->get('id') || ($this->input->getMethod() === 'POST' && $vName === 'tags'))
		{
			$cachable = false;
		}

		$safeurlparams = array(
			'id'               => 'ARRAY',
			'type'             => 'ARRAY',
			'limit'            => 'UINT',
			'limitstart'       => 'UINT',
			'filter_order'     => 'CMD',
			'filter_order_Dir' => 'CMD',
			'lang'             => 'CMD'
		);

		return parent::display($cachable, $safeurlparams);
	}
}
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.php000060400000000741152453734450010021 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;

JLoader::register('TagsHelperRoute', JPATH_COMPONENT . '/helpers/route.php');

$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.php000060400000011066152453734450013513 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\Dispatcher;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Dispatcher\Dispatcher as AdminDispatcher;
use Akeeba\Backup\Admin\Helper\SecretWord;
use Akeeba\Engine\Factory;
use Akeeba\Engine\Platform;
use FOF40\Container\Container;
use FOF40\Dispatcher\Exception\AccessForbidden;
use Joomla\CMS\Document\Document;
use Joomla\CMS\Document\JsonDocument as JDocumentJSON;
use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\Language\Text;

class Dispatcher extends AdminDispatcher
{
	/** @var   string  The name of the default view, in case none is specified */
	public $defaultView = 'Backup';

	/**
	 * Dispatcher constructor. Overridden to set up a different default view and migrated views map than the back-end.
	 *
	 * @param   Container  $container  The component's container
	 * @param   array      $config     Optional configuration overrides
	 */
	public function __construct(Container $container, array $config)
	{
		parent::__construct($container, $config);

		$this->defaultView = 'Backup';

		$this->viewNameAliases = [
			'backup'  => 'Backup',
			'backups' => 'Backup',
			'check'   => 'Check',
			'checks'  => 'Check',
			'json'    => 'Json',
			'jsons'   => 'Json',
		];
	}


	/**
	 * Executes before dispatching the request to the appropriate controller
	 */
	public function onBeforeDispatch()
	{
		// 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'));
		}

		// Core version: there is no front-end, throw a 403
		if (!defined('AKEEBA_PRO') || !AKEEBA_PRO)
		{
			throw new AccessForbidden(Text::_('COM_AKEEBA_ERR_NO_FRONTEND_IN_CORE'));
		}

//		$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_SITE, 'en-GB', true, true);
		$lang->load('lib_fof40', JPATH_SITE, null, true, false);

		// Necessary defines for Akeeba Engine
		if (!defined('AKEEBAENGINE'))
		{
			define('AKEEBAENGINE', 1);
			define('AKEEBAROOT', $this->container->backEndPath . '/BackupEngine');
			define('ALICEROOT', $this->container->backEndPath . '/AliceEngine');
		}

		// 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';

		// Load the Akeeba Engine configuration
		Platform::addPlatform('joomla3x', JPATH_COMPONENT_ADMINISTRATOR . '/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
		$this->fixPDOMySQLResourceSharing();

		// Load the utils helper library
		Platform::getInstance()->load_version_defines();

		// Make sure the front-end backup Secret Word is stored encrypted
		$params = $this->container->params;
		SecretWord::enforceEncryption($params, 'frontend_secret_word');

		// Create a media file versioning tag
		$this->container->mediaVersion = md5(AKEEBA_VERSION . AKEEBA_DATE);
	}

	public function onAfterDispatch()
	{
		// Make sure that Api and Json views forcibly get format=json
		if (in_array($this->view, ['Api', 'Json']))
		{
			$format = $this->input->getCmd('format', 'html');

			if ($format == 'json')
			{
				return;
			}

			$app     = JFactory::getApplication();

			// Disable caching, disable offline, force use of index.php
			$app->set('caching', 0);
			$app->set('offline', 0);
			$app->set('themeFile', 'index.php');

			/** @var \Joomla\CMS\Document\JsonDocument $doc */
			$doc = Document::getInstance('json');

			$app->loadDocument($doc);

			if (property_exists(JFactory::class, 'document'))
			{
				JFactory::$document = $doc;
			}

			// Set a custom document name
			/** @var JDocumentJSON $document */
			$document = $this->container->platform->getDocument();
			$document->setName('akeeba_backup');

		}
	}
}
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.php000060400000000564152453734450012005 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;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Updates as AdminModel;

class Updates extends AdminModel
{
}
com_akeeba/Model/Profiles.php000060400000000566152453734450012165 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;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Profiles as AdminModel;

class Profiles extends AdminModel
{
}
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.php000060400000000572152453734450012531 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;

// Protect from unauthorized access
defined('_JEXEC') || die();

use Akeeba\Backup\Admin\Model\Statistics as AdminModel;

class Statistics extends AdminModel
{
}
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.php000060400000001476152453734450010553 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;

if (version_compare(PHP_VERSION, '7.2.0', 'lt'))
{
	die('PHP 7.2 or later is required.');
}

if (!defined('FOF40_INCLUDED') && !@include_once(JPATH_LIBRARIES . '/fof40/include.php'))
{
	throw new RuntimeException('This extension requires FOF 4.', 500);
}

$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();
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.php000060400000000613152453734450007425 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;

require_once JPATH_ADMINISTRATOR . '/components/com_jce/jce.php';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.php000060400000001327152453734450010040 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' );

// Include dependencies
jimport('joomla.application.component.controller');

# For compatibility with older versions of Joola 2.5
if (!class_exists('JControllerLegacy')){
    class JControllerLegacy extends JController {

    }
}

require_once(JPATH_COMPONENT.'/displayer.php');

$controller = JControllerLegacy::getInstance('Xmap');
$controller->execute(JRequest::getVar('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.php000060400000020244152453734450011501 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.database.query');

/**
 * Xmap Component Sitemap Model
 *
 * @package        Xmap
 * @subpackage     com_xmap
 * @since          2.0
 */
class XmapHelper
{

    public static function &getMenuItems($selections)
    {
        $db = JFactory::getDbo();
        $app = JFactory::getApplication();
        $user = JFactory::getUser();
        $list = array();

        foreach ($selections as $menutype => $menuOptions) {
            // Initialize variables.
            // Get the menu items as a tree.
            $query = $db->getQuery(true);
            $query->select(
                    'n.id, n.title, n.alias, n.path, n.level, n.link, '
                  . 'n.type, n.params, n.home, n.parent_id'
                  . ',n.'.$db->quoteName('browserNav')
                  );
            $query->from('#__menu AS n');
            $query->join('INNER', ' #__menu AS p ON p.lft = 0');
            $query->where('n.lft > p.lft');
            $query->where('n.lft < p.rgt');
            $query->order('n.lft');

            // Filter over the appropriate menu.
            $query->where('n.menutype = ' . $db->quote($menutype));

            // Filter over authorized access levels and publishing state.
            $query->where('n.published = 1');
            $query->where('n.access IN (' . implode(',', (array) $user->getAuthorisedViewLevels()) . ')');

            // Filter by language
            if ($app->getLanguageFilter()) {
                $query->where('n.language in ('.$db->quote(JFactory::getLanguage()->getTag()).','.$db->quote('*').')');
            }

            // Get the list of menu items.
            $db->setQuery($query);
            $tmpList = $db->loadObjectList('id');
            $list[$menutype] = array();

            // Check for a database error.
            if ($db->getErrorNum()) {
                JError::raiseWarning(021, $db->getErrorMsg());
                return array();
            }

            // Set some values to make nested HTML rendering easier.
            foreach ($tmpList as $id => $item) {
                $item->items = array();

                $params = new JRegistry($item->params);
                $item->uid = 'itemid'.$item->id;

                if (preg_match('#^/?index.php.*option=(com_[^&]+)#', $item->link, $matches)) {
                    $item->option = $matches[1];
                    $componentParams = clone(JComponentHelper::getParams($item->option));
                    $componentParams->merge($params);
                    //$params->merge($componentParams);
                    $params = $componentParams;
                } else {
                    $item->option = null;
                }

                $item->params = $params;

                if ($item->type != 'separator') {

                    $item->priority = $menuOptions['priority'];
                    $item->changefreq = $menuOptions['changefreq'];

                    XmapHelper::prepareMenuItem($item);
                } else {
                    $item->priority = null;
                    $item->changefreq = null;
                }

                if ($item->parent_id > 1) {
                    $tmpList[$item->parent_id]->items[$item->id] = $item;
                } else {
                    $list[$menutype][$item->id] = $item;
                }
            }
        }
        return $list;
    }

    public static function &getExtensions()
    {
        static $list;

        jimport('joomla.html.parameter');

        if ($list != null) {
            return $list;
        }
        $db = JFactory::getDBO();

        $list = array();
        // Get the menu items as a tree.
        $query = $db->getQuery(true);
        $query->select('*');
        $query->from('#__extensions AS n');
        $query->where('n.folder = \'xmap\'');
        $query->where('n.enabled = 1');

        // Get the list of menu items.
        $db->setQuery($query);
        $extensions = $db->loadObjectList('element');

        foreach ($extensions as $element => $extension) {
            if (file_exists(JPATH_PLUGINS . '/' . $extension->folder . '/' . $element. '/'. $element . '.php')) {
                require_once(JPATH_PLUGINS . '/' . $extension->folder . '/' . $element. '/'. $element . '.php');
                $params = new JRegistry($extension->params);
                $extension->params = $params->toArray();
                $list[$element] = $extension;
            }
        }

        return $list;
    }

    /**
     * Call the function prepareMenuItem of the extension for the item (if any)
     *
     * @param    object        Menu item object
     *
     * @return    void
     */
    public static function prepareMenuItem($item)
    {
        $extensions = XmapHelper::getExtensions();
        if (!empty($extensions[$item->option])) {
            $className = 'xmap_' . $item->option;
            $obj = new $className;
            if (method_exists($obj, 'prepareMenuItem')) {
                $obj->prepareMenuItem($item,$extensions[$item->option]->params);
            }
        }
    }


    static function getImages($text,$max)
    {
        if (!isset($urlBase)) {
            $urlBase = JURI::base();
            $urlBaseLen = strlen($urlBase);
        }

        $images = null;
        $matches = $matches1 = $matches2 = array();
        // Look <img> tags
        preg_match_all('/<img[^>]*?(?:(?:[^>]*src="(?P<src>[^"]+)")|(?:[^>]*alt="(?P<alt>[^"]+)")|(?:[^>]*title="(?P<title>[^"]+)"))+[^>]*>/i', $text, $matches1, PREG_SET_ORDER);
        // Loog for <a> tags with href to images
        preg_match_all('/<a[^>]*?(?:(?:[^>]*href="(?P<src>[^"]+\.(gif|png|jpg|jpeg))")|(?:[^>]*alt="(?P<alt>[^"]+)")|(?:[^>]*title="(?P<title>[^"]+)"))+[^>]*>/i', $text, $matches2, PREG_SET_ORDER);
        $matches = array_merge($matches1,$matches2);
        if (count($matches)) {
            $images = array();

            $count = count($matches);
            $j = 0;
            for ($i = 0; $i < $count && $j < $max; $i++) {
                if (trim($matches[$i]['src']) && (substr($matches[$i]['src'], 0, 1) == '/' || !preg_match('/^https?:\/\//i', $matches[$i]['src']) || substr($matches[$i]['src'], 0, $urlBaseLen) == $urlBase)) {
                    $src = $matches[$i]['src'];
                    if (substr($src, 0, 1) == '/') {
                        $src = substr($src, 1);
                    }
                    if (!preg_match('/^https?:\//i', $src)) {
                        $src = $urlBase . $src;
                    }
                    $image = new stdClass;
                    $image->src = $src;
                    $image->title = (isset($matches[$i]['title']) ? $matches[$i]['title'] : @$matches[$i]['alt']);
                    $images[] = $image;
                    $j++;
                }
            }
        }
        return $images;
    }

    static function getPagebreaks($text,$baseLink)
    {
        $matches = $subnodes = array();
        if (preg_match_all(
                '/<hr\s*[^>]*?(?:(?:\s*alt="(?P<alt>[^"]+)")|(?:\s*title="(?P<title>[^"]+)"))+[^>]*>/i',
                $text, $matches, PREG_SET_ORDER)
        ) {
            $i = 2;
            foreach ($matches as $match) {
                if (strpos($match[0], 'class="system-pagebreak"') !== FALSE) {
                    $link = $baseLink . '&limitstart=' . ($i - 1);

                    if (@$match['alt']) {
                        $title = stripslashes($match['alt']);
                    } elseif (@$match['title']) {
                        $title = stripslashes($match['title']);
                    } else {
                        $title = JText::sprintf('Page #', $i);
                    }
                    $subnode = new stdclass();
                    $subnode->name = $title;
                    $subnode->expandible = false;
                    $subnode->link = $link;
                    $subnodes[] = $subnode;
                    $i++;
                }
            }

        }
        return $subnodes;
    }
}
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.php000060400000003623152453734450011257 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.controller');

/**
 * Xmap Component Controller
 *
 * @package        Xmap
 * @subpackage     com_xmap
 * @since          2.0
 */
class XmapController extends JControllerLegacy
{

    /**
     * Method to display a view.
     *
     * @param   boolean         If true, the view output will be cached
     * @param   array           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)
    {
        $cachable = true;

        $id         = JRequest::getInt('id');
        $viewName   = JRequest::getCmd('view');
        $viewLayout = JRequest::getCmd('layout', 'default');

        $user = JFactory::getUser();

        if ($user->get('id') || !in_array($viewName, array('html', 'xml')) || $viewLayout == 'xsl') {
            $cachable = false;
        }

        if ($viewName) {
            $document = JFactory::getDocument();
            $viewType = $document->getType();
            $view = $this->getView($viewName, $viewType, '', array('base_path' => $this->basePath, 'layout' => $viewLayout));
            $sitemapmodel = $this->getModel('Sitemap');
            $view->setModel($sitemapmodel, true);
        }

        $safeurlparams = array('id' => 'INT', 'itemid' => 'INT', 'uid' => 'CMD', 'action' => 'CMD', 'property' => 'CMD', 'value' => 'CMD');

        parent::display($cachable, $safeurlparams);

        return $this;
    }

}
com_xmap/models/index.html000060400000000036152453734450011636 0ustar00<!DOCTYPE html><title></title>com_xmap/models/sitemap.php000060400000023144152453734450012021 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.modelitem');
jimport('joomla.database.query');
require_once(JPATH_COMPONENT . '/helpers/xmap.php');

/**
 * Xmap Component Sitemap Model
 *
 * @package        Xmap
 * @subpackage     com_xmap
 * @since          2.0
 */
class XmapModelSitemap extends JModelItem
{

    /**
     * Model context string.
     *
     * @var        string
     */
    protected $_context = 'com_xmap.sitemap';
    protected $_extensions = null;

    static $items = array();
    /**
     * Method to auto-populate the model state.
     *
     * @return     void
     */
    protected function populateState()
    {
        $app = JFactory::getApplication('site');

        // Load state from the request.
        $pk = JRequest::getInt('id');
        $this->setState('sitemap.id', $pk);

        $offset = JRequest::getInt('limitstart');
        $this->setState('list.offset', $offset);

        // Load the parameters.
        $params = $app->getParams();
        $this->setState('params', $params);

        // TODO: Tune these values based on other permissions.
        $this->setState('filter.published', 1);
        $this->setState('filter.access', true);
    }

    /**
     * Method to get sitemap data.
     *
     * @param    integer    The id of the article.
     *
     * @return   mixed      Menu item data object on success, false on failure.
     */
    public function &getItem($pk = null)
    {
        // Initialize variables.
        $db = $this->getDbo();
        $pk = (!empty($pk)) ? $pk : (int) $this->getState('sitemap.id');

        // If not sitemap specified, select the default one
        if (!$pk) {
            $query = $db->getQuery(true);
            $query->select('id')->from('#__xmap_sitemap')->where('is_default=1');
            $db->setQuery($query);
            $pk = $db->loadResult();
        }

        if ($this->_item === null) {
            $this->_item = array();
        }

        if (!isset($this->_item[$pk])) {
            try {
                $query = $db->getQuery(true);

                $query->select($this->getState('item.select', 'a.*'));
                $query->from('#__xmap_sitemap AS a');

                $query->where('a.id = ' . (int) $pk);

                // Filter by published state.
                $published = $this->getState('filter.published');
                if (is_numeric($published)) {
                    $query->where('a.state = ' . (int) $published);
                }

                // Filter by access level.
                if ($access = $this->getState('filter.access')) {
                    $user = JFactory::getUser();
                    $groups = implode(',', $user->getAuthorisedViewLevels());
                    $query->where('a.access IN (' . $groups . ')');
                }

                $this->_db->setQuery($query);

                $data = $this->_db->loadObject();

                if ($error = $this->_db->getErrorMsg()) {
                    throw new Exception($error);
                }

                if (empty($data)) {
                    throw new Exception(JText::_('COM_XMAP_ERROR_SITEMAP_NOT_FOUND'));
                }

                // Check for published state if filter set.
                if (is_numeric($published) && $data->state != $published) {
                    throw new Exception(JText::_('COM_XMAP_ERROR_SITEMAP_NOT_FOUND'));
                }

                // Convert parameter fields to objects.
                $registry = new JRegistry('_default');
                $registry->loadString($data->attribs);
                $data->params = clone $this->getState('params');
                $data->params->merge($registry);

                // Convert the selections field to an array.
                $registry = new JRegistry('_default');
                $registry->loadString($data->selections);
                $data->selections = $registry->toArray();

                // Compute access permissions.
                if ($access) {
                    // If the access filter has been set, we already know this user can view.
                    $data->params->set('access-view', true);
                } else {
                    // If no access filter is set, the layout takes some responsibility for display of limited information.
                    $user = &JFactory::getUser();
                    $groups = $user->authorisedLevels();

                    $data->params->set('access-view', in_array($data->access, $groups));
                }
                // TODO: Type 2 permission checks?

                $this->_item[$pk] = $data;
            } catch (Exception $e) {
                $this->setError($e->getMessage());
                $this->_item[$pk] = false;
            }
        }

        return $this->_item[$pk];
    }

    public function getItems()
    {
        if ($item = $this->getItem()) {
            return XmapHelper::getMenuItems($item->selections);
        }
        return false;
    }

    function getExtensions()
    {
        return XmapHelper::getExtensions();
    }

    /**
     * Increment the hit counter for the sitemap.
     *
     * @param    int        Optional primary key of the sitemap to increment.
     *
     * @return   boolean    True if successful; false otherwise and internal error set.
     */
    public function hit($count)
    {
        // Initialize variables.
        $pk = (int) $this->getState('sitemap.id');

        $view = JRequest::getCmd('view', 'html');
        if ($view != 'xml' && $view != 'html') {
            return false;
        }

        $this->_db->setQuery(
            'UPDATE #__xmap_sitemap' .
            ' SET views_' . $view . ' = views_' . $view . ' + 1, count_' . $view . ' = ' . $count . ', lastvisit_' . $view . ' = ' . JFactory::getDate()->toUnix() .
            ' WHERE id = ' . (int) $pk
        );

        if (!$this->_db->query()) {
            $this->setError($this->_db->getErrorMsg());
            return false;
        }

        return true;
    }

    public function getSitemapItems($view=null)
    {
        if (!isset($view)) {
            $view = JRequest::getCmd('view');
        }
        $db = JFactory::getDBO();
        $pk = (int) $this->getState('sitemap.id');

        if (self::$items !== NULL && isset(self::$items[$view])) {
            return;
        }
        $query = "select * from #__xmap_items where view='$view' and sitemap_id=" . $pk;
        $db->setQuery($query);
        $rows = $db->loadObjectList();
        self::$items[$view] = array();
        foreach ($rows as $row) {
            self::$items[$view][$row->itemid] = array();
            self::$items[$view][$row->itemid][$row->uid] = array();
            $pairs = explode(';', $row->properties);
            foreach ($pairs as $pair) {
                if (strpos($pair, '=') !== FALSE) {
                    list($property, $value) = explode('=', $pair);
                    self::$items[$view][$row->itemid][$row->uid][$property] = $value;
                }
            }
        }
        return self::$items;
    }

    function chageItemPropery($uid, $itemid, $view, $property, $value)
    {
        $items = $this->getSitemapItems($view);
        $db = JFactory::getDBO();
        $pk = (int) $this->getState('sitemap.id');

        $isNew = false;
        if (empty($items[$view][$itemid][$uid])) {
            $items[$view][$itemid][$uid] = array();
            $isNew = true;
        }
        $items[$view][$itemid][$uid][$property] = $value;
        $sep = $properties = '';
        foreach ($items[$view][$itemid][$uid] as $k => $v) {
            $properties .= $sep . $k . '=' . $v;
            $sep = ';';
        }
        if (!$isNew) {
            $query = 'UPDATE #__xmap_items SET properties=\'' . $db->escape($properties) . "' where uid='" . $db->escape($uid) . "' and itemid=$itemid and view='$view' and sitemap_id=" . $pk;
        } else {
            $query = 'INSERT #__xmap_items (uid,itemid,view,sitemap_id,properties) values ( \'' . $db->escape($uid) . "',$itemid,'$view',$pk,'" . $db->escape($properties) . "')";
        }
        $db->setQuery($query);
        //echo $db->getQuery();exit;
        if ($db->query()) {
            return true;
        } else {
            return false;
        }
    }

    function toggleItem($uid, $itemid)
    {
        $app = JFactory::getApplication('site');
        $sitemap = $this->getItem();

        $displayer = new XmapDisplayer($app->getParams(), $sitemap);

        $excludedItems = $displayer->getExcludedItems();
        if (isset($excludedItems[$itemid])) {
            $excludedItems[$itemid] = (array) $excludedItems[$itemid];
        }
        if (!$displayer->isExcluded($itemid, $uid)) {
            $excludedItems[$itemid][] = $uid;
            $state = 0;
        } else {
            if (is_array($excludedItems[$itemid]) && count($excludedItems[$itemid])) {
                $excludedItems[$itemid] = array_filter($excludedItems[$itemid], create_function('$var', 'return ($var != \'' . $uid . '\');'));
            } else {
                unset($excludedItems[$itemid]);
            }
            $state = 1;
        }

        $registry = new JRegistry('_default');
        $registry->loadArray($excludedItems);
        $str = $registry->toString();

        $db = JFactory::getDBO();
        $query = "UPDATE #__xmap_sitemap set excluded_items='" . $db->escape($str) . "' where id=" . $sitemap->id;
        $db->setQuery($query);
        $db->query();
        return $state;
    }

}
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.php000060400000000630152453734450011202 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

$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.php000060400000001331152453734450011734 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;

/**
 * Banners Controller
 *
 * @since  1.5
 */
class BannersController extends JControllerLegacy
{
	/**
	 * Method when a banner is clicked on.
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function click()
	{
		$id = $this->input->getInt('id', 0);

		if ($id)
		{
			$model = $this->getModel('Banner', 'BannersModel', array('ignore_request' => true));
			$model->setState('banner.id', $id);
			$model->click();
			$this->setRedirect($model->getUrl());
		}
	}
}
com_banners/models/banner.php000060400000010221152453734450012277 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;

JTable::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/tables');

/**
 * Banner model for the Joomla Banners component.
 *
 * @since  1.5
 */
class BannersModelBanner extends JModelLegacy
{
	/**
	 * Cached item object
	 *
	 * @var    object
	 * @since  1.6
	 */
	protected $_item;

	/**
	 * Clicks the URL, incrementing the counter
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function click()
	{
		$item = $this->getItem();

		if (empty($item))
		{
			throw new Exception(JText::_('JERROR_PAGE_NOT_FOUND'), 404);
		}

		$id = $this->getState('banner.id');

		// Update click count
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->update('#__banners')
			->set('clicks = (clicks + 1)')
			->where('id = ' . (int) $id);

		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (RuntimeException $e)
		{
			JError::raiseError(500, $e->getMessage());
		}

		// Track clicks
		$trackClicks = $item->track_clicks;

		if ($trackClicks < 0 && $item->cid)
		{
			$trackClicks = $item->client_track_clicks;
		}

		if ($trackClicks < 0)
		{
			$config = JComponentHelper::getParams('com_banners');
			$trackClicks = $config->get('track_clicks');
		}

		if ($trackClicks > 0)
		{
			$trackDate = JFactory::getDate()->format('Y-m-d H:00:00');
			$trackDate = JFactory::getDate($trackDate)->toSql();

			$query->clear()
				->select($db->quoteName('count'))
				->from('#__banner_tracks')
				->where('track_type=2')
				->where('banner_id=' . (int) $id)
				->where('track_date=' . $db->quote($trackDate));

			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				JError::raiseError(500, $e->getMessage());
			}

			$count = $db->loadResult();

			$query->clear();

			if ($count)
			{
				// Update count
				$query->update('#__banner_tracks')
					->set($db->quoteName('count') . ' = (' . $db->quoteName('count') . ' + 1)')
					->where('track_type=2')
					->where('banner_id=' . (int) $id)
					->where('track_date=' . $db->quote($trackDate));
			}
			else
			{
				// Insert new count
				$query->insert('#__banner_tracks')
					->columns(
						array(
							$db->quoteName('count'), $db->quoteName('track_type'),
							$db->quoteName('banner_id'), $db->quoteName('track_date')
						)
					)
					->values('1, 2,' . (int) $id . ',' . $db->quote($trackDate));
			}

			$db->setQuery($query);

			try
			{
				$db->execute();
			}
			catch (RuntimeException $e)
			{
				JError::raiseError(500, $e->getMessage());
			}
		}
	}

	/**
	 * Get the data for a banner.
	 *
	 * @return  object
	 *
	 * @since   1.6
	 */
	public function &getItem()
	{
		if (!isset($this->_item))
		{
			/** @var JCacheControllerCallback $cache */
			$cache = JFactory::getCache('com_banners', 'callback');

			$id = $this->getState('banner.id');

			// For PHP 5.3 compat we can't use $this in the lambda function below, so grab the database driver now to use it
			$db = $this->getDbo();

			$loader = function ($id) use ($db)
			{
				$query = $db->getQuery(true)
					->select(
						array(
							$db->quoteName('a.clickurl', 'clickurl'),
							$db->quoteName('a.cid', 'cid'),
							$db->quoteName('a.track_clicks', 'track_clicks'),
							$db->quoteName('cl.track_clicks', 'client_track_clicks'),
						)
					)
					->from($db->quoteName('#__banners', 'a'))
					->join('LEFT', '#__banner_clients AS cl ON cl.id = a.cid')
					->where('a.id = ' . (int) $id);

				$db->setQuery($query);

				return $db->loadObject();
			};

			try
			{
				$this->_item = $cache->get($loader, array($id), md5(__METHOD__ . $id));
			}
			catch (JCacheException $e)
			{
				$this->_item = $loader($id);
			}
		}

		return $this->_item;
	}

	/**
	 * Get the URL for a banner
	 *
	 * @return  string
	 *
	 * @since   1.5
	 */
	public function getUrl()
	{
		$item = $this->getItem();
		$url = $item->clickurl;

		// Check for links
		if (!preg_match('#http[s]?://|index[2]?\.php#', $url))
		{
			$url = "http://$url";
		}

		return $url;
	}
}
com_banners/models/banners.php000060400000021130152453734450012463 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;

use Joomla\Registry\Registry;
use Joomla\Utilities\ArrayHelper;

JTable::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/tables');

/**
 * Banners model for the Joomla Banners component.
 *
 * @since  1.6
 */
class BannersModelBanners extends JModelList
{
	/**
	 * 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.tag_search');
		$id .= ':' . $this->getState('filter.client_id');
		$id .= ':' . serialize($this->getState('filter.category_id'));
		$id .= ':' . serialize($this->getState('filter.keywords'));

		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   1.6
	 */
	protected function getListQuery()
	{
		$db         = $this->getDbo();
		$query      = $db->getQuery(true);
		$ordering   = $this->getState('filter.ordering');
		$tagSearch  = $this->getState('filter.tag_search');
		$cid        = $this->getState('filter.client_id');
		$categoryId = $this->getState('filter.category_id');
		$keywords   = $this->getState('filter.keywords');
		$randomise  = ($ordering === 'random');
		$nullDate   = $db->quote($db->getNullDate());
		$nowDate    = $db->quote(JFactory::getDate()->toSql());

		$query->select(
			'a.id as id,'
				. 'a.type as type,'
				. 'a.name as name,'
				. 'a.clickurl as clickurl,'
				. 'a.cid as cid,'
				. 'a.description as description,'
				. 'a.params as params,'
				. 'a.custombannercode as custombannercode,'
				. 'a.track_impressions as track_impressions,'
				. 'cl.track_impressions as client_track_impressions'
		)
			->from('#__banners as a')
			->join('LEFT', '#__banner_clients AS cl ON cl.id = a.cid')
			->where('a.state=1')
			->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')')
			->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')')
			->where('(a.imptotal = 0 OR a.impmade < a.imptotal)');

		if ($cid)
		{
			$query->where('a.cid = ' . (int) $cid)
				->where('cl.state = 1');
		}

		// Filter by a single or group of categories
		if (is_numeric($categoryId))
		{
			$type = $this->getState('filter.category_id.include', true) ? '= ' : '<> ';

			// Add subcategory check
			$includeSubcategories = $this->getState('filter.subcategories', false);
			$categoryEquals = 'a.catid ' . $type . (int) $categoryId;

			if ($includeSubcategories)
			{
				$levels = (int) $this->getState('filter.max_category_levels', '1');

				// Create a subquery for the subcategory list
				$subQuery = $db->getQuery(true);
				$subQuery->select('sub.id')
					->from('#__categories as sub')
					->join('INNER', '#__categories as this ON sub.lft > this.lft AND sub.rgt < this.rgt')
					->where('this.id = ' . (int) $categoryId)
					->where('sub.level <= this.level + ' . $levels);

				// Add the subquery to the main query
				$query->where('(' . $categoryEquals . ' OR a.catid IN (' . (string) $subQuery . '))');
			}
			else
			{
				$query->where($categoryEquals);
			}
		}
		elseif (is_array($categoryId) && (count($categoryId) > 0))
		{
			$categoryId = ArrayHelper::toInteger($categoryId);
			$categoryId = implode(',', $categoryId);

			if ($categoryId != '0')
			{
				$type = $this->getState('filter.category_id.include', true) ? 'IN' : 'NOT IN';
				$query->where('a.catid ' . $type . ' (' . $categoryId . ')');
			}
		}

		if ($tagSearch)
		{
			if (!$keywords)
			{
				$query->where('0 != 0');
			}
			else
			{
				$temp   = array();
				$config = JComponentHelper::getParams('com_banners');
				$prefix = $config->get('metakey_prefix');

				if ($categoryId)
				{
					$query->join('LEFT', '#__categories as cat ON a.catid = cat.id');
				}

				foreach ($keywords as $keyword)
				{
					$condition1 = 'a.own_prefix=1 '
						. ' AND a.metakey_prefix=SUBSTRING(' . $db->quote($keyword) . ',1,LENGTH( a.metakey_prefix)) '
						. ' OR a.own_prefix=0 '
						. ' AND cl.own_prefix=1 '
						. ' AND cl.metakey_prefix=SUBSTRING(' . $db->quote($keyword) . ',1,LENGTH(cl.metakey_prefix)) '
						. ' OR a.own_prefix=0 '
						. ' AND cl.own_prefix=0 '
						. ' AND ' . ($prefix == substr($keyword, 0, strlen($prefix)) ? '0 = 0' : '0 != 0');

					$regexp = $db->quote("[[:<:]]" . $db->escape($keyword) . "[[:>:]]");
					$condition2 = "a.metakey " . $query->regexp($regexp) . " ";

					if ($cid)
					{
						$condition2 .= " OR cl.metakey " . $query->regexp($regexp) . " ";
					}

					if ($categoryId)
					{
						$condition2 .= " OR cat.metakey " . $query->regexp($regexp) . " ";
					}

					$temp[] = "($condition1) AND ($condition2)";
				}

				$query->where('(' . implode(' OR ', $temp) . ')');
			}
		}

		// Filter by language
		if ($this->getState('filter.language'))
		{
			$query->where('a.language in (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		$query->order('a.sticky DESC,' . ($randomise ? $query->Rand() : 'a.ordering'));

		return $query;
	}

	/**
	 * Get a list of banners.
	 *
	 * @return  array
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		if ($this->getState('filter.tag_search'))
		{
			// Filter out empty keywords.
			$keywords = array_values(array_filter(array_map('trim', $this->getState('filter.keywords')), 'strlen'));

			// Re-set state before running the query.
			$this->setState('filter.keywords', $keywords);

			// If no keywords are provided, avoid running the query.
			if (!$keywords)
			{
				$this->cache['items'] = array();

				return $this->cache['items'];
			}
		}

		if (!isset($this->cache['items']))
		{
			$this->cache['items'] = parent::getItems();

			foreach ($this->cache['items'] as &$item)
			{
				$item->params = new Registry($item->params);
			}
		}

		return $this->cache['items'];
	}

	/**
	 * Makes impressions on a list of banners
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function impress()
	{
		$trackDate = JFactory::getDate()->format('Y-m-d H:00:00');
		$trackDate = JFactory::getDate($trackDate)->toSql();

		$items     = $this->getItems();
		$db        = $this->getDbo();
		$query     = $db->getQuery(true);

		if (!count($items))
		{
			return;
		}

		foreach ($items as $item)
		{
			$bid[] = (int) $item->id;
		}

		// Increment impression made
		$query->clear()
			->update('#__banners')
			->set('impmade = (impmade + 1)')
			->where('id IN (' . implode(',', $bid) . ')');
		$db->setQuery($query);

		try
		{
			$db->execute();
		}
		catch (JDatabaseExceptionExecuting $e)
		{
			JError::raiseError(500, $e->getMessage());
		}

		foreach ($items as $item)
		{
			// Track impressions
			$trackImpressions = $item->track_impressions;

			if ($trackImpressions < 0 && $item->cid)
			{
				$trackImpressions = $item->client_track_impressions;
			}

			if ($trackImpressions < 0)
			{
				$config           = JComponentHelper::getParams('com_banners');
				$trackImpressions = $config->get('track_impressions');
			}

			if ($trackImpressions > 0)
			{
				// Is track already created?
				// Update count
				$query->clear();
				$query->update('#__banner_tracks')
					->set($db->quoteName('count') . ' = (' . $db->quoteName('count') . ' + 1)')
					->where('track_type=1')
					->where('banner_id=' . (int) $item->id)
					->where('track_date=' . $db->quote($trackDate));

				$db->setQuery($query);

				try
				{
					$db->execute();
				}
				catch (JDatabaseExceptionExecuting $e)
				{
					JError::raiseError(500, $e->getMessage());
				}

				if ($db->getAffectedRows() === 0)
				{
					// Insert new count
					$query->clear();

					$query->insert('#__banner_tracks')
						->columns(
							array(
								$db->quoteName('count'), $db->quoteName('track_type'),
								$db->quoteName('banner_id'), $db->quoteName('track_date')
							)
						)
						->values('1, 1, ' . (int) $item->id . ', ' . $db->quote($trackDate));

					$db->setQuery($query);

					try
					{
						$db->execute();
					}
					catch (JDatabaseExceptionExecuting $e)
					{
						JError::raiseError(500, $e->getMessage());
					}
				}
			}
		}
	}
}
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.php000060400000002646152453734450011773 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;

/**
 * Privacy Controller
 *
 * @since  3.9.0
 */
class PrivacyController 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  $this
	 *
	 * @since   3.9.0
	 */
	public function display($cachable = false, $urlparams = array())
	{
		$view = $this->input->get('view', $this->default_view);

		// Submitting information requests and confirmation through the frontend is restricted to authenticated users at this time
		if (in_array($view, array('confirm', 'request')) && JFactory::getUser()->guest)
		{
			$this->setRedirect(
				JRoute::_('index.php?option=com_users&view=login&return=' . base64_encode('index.php?option=com_privacy&view=' . $view), false)
			);

			return $this;
		}

		// Set a Referrer-Policy header for views which require it
		if (in_array($view, array('confirm', 'remind')))
		{
			JFactory::getApplication()->setHeader('Referrer-Policy', 'no-referrer', true);
		}

		return parent::display($cachable, $urlparams);
	}
}
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.php000060400000003114152453734450015024 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 PrivacyViewRequest $this */

JHtml::_('behavior.keepalive');
JHtml::_('behavior.formvalidator');
JHtml::_('formbehavior.chosen', 'select');

?>
<div class="request-form<?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->sendMailEnabled) : ?>
		<form action="<?php echo JRoute::_('index.php?option=com_privacy&task=request.submit'); ?>" 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>
	<?php else : ?>
		<div class="alert alert-warning">
			<p><?php echo JText::_('COM_PRIVACY_WARNING_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED'); ?></p>
		</div>
	<?php endif; ?>
</div>
com_privacy/views/request/view.html.php000060400000006330152453734450014344 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 view class
 *
 * @since  3.9.0
 */
class PrivacyViewRequest 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;

	/**
	 * Flag indicating the site supports sending email
	 *
	 * @var    boolean
	 * @since  3.9.0
	 */
	protected $sendMailEnabled;

	/**
	 * 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;
		$this->sendMailEnabled = (bool) JFactory::getConfig()->get('mailonline', 1);

		// 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_REQUEST_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/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.php000060400000010443152453734450013640 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 action controller class.
 *
 * @since  3.9.0
 */
class PrivacyControllerRequest extends JControllerLegacy
{
	/**
	 * Method to confirm the information request.
	 *
	 * @return  boolean
	 *
	 * @since   3.9.0
	 */
	public function confirm()
	{
		// Check the request token.
		$this->checkToken('post');

		/** @var PrivacyModelConfirm $model */
		$model = $this->getModel('Confirm', 'PrivacyModel');
		$data  = $this->input->post->get('jform', array(), 'array');

		$return	= $model->confirmRequest($data);

		// Check for a hard error.
		if ($return instanceof Exception)
		{
			// Get the error message to display.
			if (JFactory::getApplication()->get('error_reporting'))
			{
				$message = $return->getMessage();
			}
			else
			{
				$message = JText::_('COM_PRIVACY_ERROR_CONFIRMING_REQUEST');
			}

			// Go back to the confirm form.
			$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=confirm', false), $message, 'error');

			return false;
		}
		elseif ($return === false)
		{
			// Confirm failed.
			// Go back to the confirm form.
			$message = JText::sprintf('COM_PRIVACY_ERROR_CONFIRMING_REQUEST_FAILED', $model->getError());
			$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=confirm', false), $message, 'notice');

			return false;
		}
		else
		{
			// Confirm succeeded.
			$this->setRedirect(JRoute::_(JUri::root()), JText::_('COM_PRIVACY_CONFIRM_REQUEST_SUCCEEDED'), 'info');

			return true;
		}
	}

	/**
	 * Method to submit an information request.
	 *
	 * @return  boolean
	 *
	 * @since   3.9.0
	 */
	public function submit()
	{
		// Check the request token.
		$this->checkToken('post');

		/** @var PrivacyModelRequest $model */
		$model = $this->getModel('Request', 'PrivacyModel');
		$data  = $this->input->post->get('jform', array(), 'array');

		$return	= $model->createRequest($data);

		// Check for a hard error.
		if ($return instanceof Exception)
		{
			// Get the error message to display.
			if (JFactory::getApplication()->get('error_reporting'))
			{
				$message = $return->getMessage();
			}
			else
			{
				$message = JText::_('COM_PRIVACY_ERROR_CREATING_REQUEST');
			}

			// Go back to the confirm form.
			$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=request', false), $message, 'error');

			return false;
		}
		elseif ($return === false)
		{
			// Confirm failed.
			// Go back to the confirm form.
			$message = JText::sprintf('COM_PRIVACY_ERROR_CREATING_REQUEST_FAILED', $model->getError());
			$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=request', false), $message, 'notice');

			return false;
		}
		else
		{
			// Confirm succeeded.
			$this->setRedirect(JRoute::_(JUri::root()), JText::_('COM_PRIVACY_CREATE_REQUEST_SUCCEEDED'), 'info');

			return true;
		}
	}

	/**
	 * Method to extend the privacy consent.
	 *
	 * @return  boolean
	 *
	 * @since   3.9.0
	 */
	public function remind()
	{
		// Check the request token.
		$this->checkToken('post');

		/** @var PrivacyModelConfirm $model */
		$model = $this->getModel('Remind', 'PrivacyModel');
		$data  = $this->input->post->get('jform', array(), 'array');

		$return	= $model->remindRequest($data);

		// Check for a hard error.
		if ($return instanceof Exception)
		{
			// Get the error message to display.
			if (JFactory::getApplication()->get('error_reporting'))
			{
				$message = $return->getMessage();
			}
			else
			{
				$message = JText::_('COM_PRIVACY_ERROR_REMIND_REQUEST');
			}

			// Go back to the confirm form.
			$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=remind', false), $message, 'error');

			return false;
		}
		elseif ($return === false)
		{
			// Confirm failed.
			// Go back to the confirm form.
			$message = JText::sprintf('COM_PRIVACY_ERROR_CONFIRMING_REMIND_FAILED', $model->getError());
			$this->setRedirect(JRoute::_('index.php?option=com_privacy&view=remind', false), $message, 'notice');

			return false;
		}
		else
		{
			// Confirm succeeded.
			$this->setRedirect(JRoute::_(JUri::root()), JText::_('COM_PRIVACY_CONFIRM_REMIND_SUCCEEDED'), 'info');

			return true;
		}
	}
}
com_privacy/privacy.php000060400000000630152453734450011254 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;

$controller = JControllerLegacy::getInstance('Privacy');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_privacy/models/request.php000060400000016533152453734450012563 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\CMS\Router\Route;

/**
 * Request model class.
 *
 * @since  3.9.0
 */
class PrivacyModelRequest extends JModelAdmin
{
	/**
	 * Creates an information request.
	 *
	 * @param   array  $data  The data expected for the form.
	 *
	 * @return  mixed  Exception | JException | boolean
	 *
	 * @since   3.9.0
	 */
	public function createRequest($data)
	{
		// Creating requests requires the site's email sending be enabled
		if (!JFactory::getConfig()->get('mailonline', 1))
		{
			$this->setError(JText::_('COM_PRIVACY_ERROR_CANNOT_CREATE_REQUEST_WHEN_SENDMAIL_DISABLED'));

			return false;
		}

		// 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 an open information request matching the email and type
		$db = $this->getDbo();
		$query = $db->getQuery(true)
			->select('COUNT(id)')
			->from('#__privacy_requests')
			->where('email = ' . $db->quote($data['email']))
			->where('request_type = ' . $db->quote($data['request_type']))
			->where('status IN (0, 1)');

		try
		{
			$result = (int) $db->setQuery($query)->loadResult();
		}
		catch (JDatabaseException $exception)
		{
			// Can't check for existing requests, so don't create a new one
			$this->setError(JText::_('COM_PRIVACY_ERROR_CHECKING_FOR_EXISTING_REQUESTS'));

			return false;
		}

		if ($result > 0)
		{
			$this->setError(JText::_('COM_PRIVACY_ERROR_PENDING_REQUEST_OPEN'));

			return false;
		}

		// Everything is good to go, create the request
		$token       = JApplicationHelper::getHash(JUserHelper::genRandomPassword());
		$hashedToken = JUserHelper::hashPassword($token);

		$data['confirm_token']            = $hashedToken;
		$data['confirm_token_created_at'] = JFactory::getDate()->toSql();

		if (!$this->save($data))
		{
			// The save function will set the error message, so just return here
			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_CREATED_REQUEST_SUBJECT'),
			JText::sprintf('COM_PRIVACY_ADMIN_NOTIFICATION_USER_CREATED_REQUEST_MESSAGE', $data['email'])
		);

		// 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 ($data['request_type'])
			{
				case 'export':
					$emailSubject = JText::_('COM_PRIVACY_EMAIL_REQUEST_SUBJECT_EXPORT_REQUEST');
					$emailBody    = JText::_('COM_PRIVACY_EMAIL_REQUEST_BODY_EXPORT_REQUEST');

					break;

				case 'remove':
					$emailSubject = JText::_('COM_PRIVACY_EMAIL_REQUEST_SUBJECT_REMOVE_REQUEST');
					$emailBody    = JText::_('COM_PRIVACY_EMAIL_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($data['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;
			}

			/** @var PrivacyTableRequest $table */
			$table = $this->getTable();

			if (!$table->load($this->getState($this->getName() . '.id')))
			{
				$this->setError($table->getError());

				return false;
			}

			// Log the request's creation
			JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_actionlogs/models', 'ActionlogsModel');

			$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,
			);

			/** @var ActionlogsModelActionlog $model */
			$model = JModelLegacy::getInstance('Actionlog', 'ActionlogsModel');
			$model->addLog(array($message), 'COM_PRIVACY_ACTION_LOG_CREATED_REQUEST', 'com_privacy.request');

			// The email sent and the record is saved, everything is good to go from here
			return true;
		}
		catch (phpmailerException $exception)
		{
			$this->setError($exception->getMessage());

			return false;
		}
	}

	/**
	 * 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)
	{
		return $this->loadForm('com_privacy.request', 'request', array('control' => 'jform'));
	}

	/**
	 * 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/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.xml000060400000000705152453734450013714 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="default">
		<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_REQUEST_TYPE_EXPORT</option>
			<option value="remove">COM_PRIVACY_REQUEST_TYPE_REMOVE</option>
		</field>
	</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.php000060400000000615152453734450013230 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;

include_once(JPATH_ADMINISTRATOR . '/components/com_slideshowck/models/browse.php');com_slideshowck/models/index.html000060400000000032152453734450013204 0ustar00<html><body></body></html>com_slideshowck/models/menus.php000060400000000614152453734450013055 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;

include_once(JPATH_ADMINISTRATOR . '/components/com_slideshowck/models/menus.php');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.ini000060400000000215152453734450017764 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/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.ini000060400000000154152453734450020036 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/language/index.html000060400000000055152453734450013511 0ustar00<html><body bgcolor="#FFFFFF"></body></html>
com_slideshowck/index.html000060400000000032152453734450011721 0ustar00<html><body></body></html>com_slideshowck/controllers/index.html000060400000000032152453734450014267 0ustar00<html><body></body></html>com_slideshowck/controllers/menus.php000060400000000651152453734450014141 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;

include_once(JPATH_ADMINISTRATOR . '/components/com_slideshowck/controllers/menus.php');com_slideshowck/controllers/ajax.php000060400000000650152453734450013734 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;

include_once(JPATH_ADMINISTRATOR . '/components/com_slideshowck/controllers/ajax.php');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.php000060400000000637152453734450015506 0ustar00<?php
/**
 * @name		Template Creator CK 3
 * @package		com_slideshowck
 * @copyright	Copyright (C) 2013. 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;

require_once JPATH_ADMINISTRATOR . '/components/com_slideshowck/views/browse/tmpl/default.php';com_slideshowck/views/browse/tmpl/index.html000060400000000054152453734450015337 0ustar00<html><body bgcolor="#FFFFFF"></body></html>com_slideshowck/views/browse/view.html.php000060400000000645152453734450015022 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;

require_once JPATH_ADMINISTRATOR . '/components/com_slideshowck/views/browse/view.html.php';com_slideshowck/controller.php000060400000000642152453734450012627 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;

include_once(JPATH_ADMINISTRATOR . '/components/com_slideshowck/controller.php');com_slideshowck/slideshowck.php000060400000003404152453734450012762 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);

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/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	= \Joomla\CMS\MVC\Controller\BaseController::getInstance('Slideshowck');
$controller->execute(\Joomla\CMS\Factory::getApplication()->input->get('task'));
com_media/media.php000060400000001160152453734450010257 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

// Load the com_media language files, default to the admin file and fall back to site if one isn't found
$lang = JFactory::getLanguage();
$lang->load('com_media', JPATH_ADMINISTRATOR, null, false, true)
||	$lang->load('com_media', JPATH_SITE, null, false, true);

// Hand processing over to the admin base file
require_once JPATH_COMPONENT_ADMINISTRATOR . '/media.php';
com_contenthistory/contenthistory.php000060400000001235152453734450014314 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

// Load the com_contenthistory language files, default to the admin file and fall back to site if one isn't found
$lang = JFactory::getLanguage();
$lang->load('com_contenthistory', JPATH_ADMINISTRATOR, null, false, true)
||	$lang->load('com_contenthistory', JPATH_SITE, null, false, true);

// Hand processing over to the admin base file
require_once JPATH_COMPONENT_ADMINISTRATOR . '/contenthistory.php';
com_modules/controller.php000060400000002175152453734450011763 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

/**
 * Modules manager master display controller.
 *
 * @since  3.5
 */
class ModulesController extends JControllerLegacy
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *                          Recognized key values include 'name', 'default_task', 'model_path', and
	 *                          'view_path' (this list is not meant to be comprehensive).
	 *
	 * @since   3.5
	 */
	public function __construct($config = array())
	{
		$this->input = JFactory::getApplication()->input;

		// Modules frontpage Editor Module proxying:
		if ($this->input->get('view') === 'modules' && $this->input->get('layout') === 'modal')
		{
			JHtml::_('stylesheet', 'system/adminlist.css', array('version' => 'auto', 'relative' => true));
			$config['base_path'] = JPATH_COMPONENT_ADMINISTRATOR;
		}

		parent::__construct($config);
	}
}
com_modules/modules.php000060400000001707152453734450011250 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

// Load the required admin language files
$lang   = JFactory::getLanguage();
$app    = JFactory::getApplication();
$config = array();
$lang->load('com_modules', JPATH_ADMINISTRATOR);

if ($app->input->get('view') === 'modules' && $app->input->get('layout') === 'modal')
{
	if (!JFactory::getUser()->authorise('core.create', 'com_modules'))
	{
		$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');

		return;
	}
}

if ($app->input->get('task') === 'module.orderPosition')
{
	$config['base_path'] = JPATH_COMPONENT_ADMINISTRATOR;
}

// Trigger the controller
$controller = JControllerLegacy::getInstance('Modules', $config);
$controller->execute($app->input->get('task'));
$controller->redirect();
com_modules/models/forms/filter_modules.xml000060400000005323152453734450015235 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_modules/models/fields" />

	<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="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>
	</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.php000060400000001547152453734450011204 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
error_reporting(E_ALL & ~E_NOTICE);
ini_set('display_errors', 1);
defined('_JEXEC') or die('Restricted access');

if(!defined('DS')){
  define('DS',DIRECTORY_SEPARATOR);
}

// Require the base controller
require_once (JPATH_COMPONENT . DS . 'controller.php');

// Require specific controller if requested
if ($controller = JRequest::getVar('controller')) {
    require_once (JPATH_COMPONENT . DS . 'controllers' . DS . $controller . '.php');
}

// Create the controller
$classname = 'MailjetController' . $controller;
$controller = new $classname();

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

// Redirect if set by the controller
$controller->redirect();
com_mailjet/models/mailjet.php000060400000005177152453734450012472 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();

if (!defined('DS')) {
  define('DS',DIRECTORY_SEPARATOR);
}

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');
}

/* Require the Mailjet API library */
require_once (sPrintF ('%s/components/com_mailjet/lib/lib/mailjet-api-strategy.php', JPATH_ADMINISTRATOR));

class MailjetModelMailjet extends JModelLegacy {

    protected $api;
    protected $params;

    function __construct()
    {
        parent::__construct();
        $this->params = $this->getAsRecord();
        $this->api = new Mailjet_Api($this->params['username'], $this->params['password']);				
    }
	
    function store(){
    	// Get the data which we'll save
        $email = filter_var($_POST['mailjet-email'], FILTER_SANITIZE_EMAIL);
        $list_id = filter_var($_POST['mailjet-list_id'], FILTER_SANITIZE_NUMBER_INT);
        if (empty($email)) $email = filter_var($_GET['mailjet-email'], FILTER_SANITIZE_EMAIL);
        if (empty($list_id)) $list_id = filter_var($_GET['mailjet-list_id'], FILTER_SANITIZE_NUMBER_INT);
        if ((empty($email)) || (empty($list_id))) return false;
	
		// Add the contact to the contact list
        $response = $this->api->addContact(array(
            'Email' => $email,
            'ListID' => $list_id
        ));
		
        if(isset($response->Status) && $response->Status == 'OK')
            return true;
        return false;
    }

    public function getAsRecord ()
    {
        //Below are some comments containing error messages to improve usability
        $credentials = sPrintF ('%s/components/%s/lib/db/data', JPATH_ADMINISTRATOR, 'com_mailjet');

        if(file_exists($credentials)){
            
            $pre_data = null;
            $content = trim(file_get_contents($credentials));
            
            if ($content) {
                $pre_data = json_decode($content);
            }

            /*if(!$pre_data->apiKey || !$pre_data->apiSecret){
                JError::raiseWarning( 100, JText::_("COM_MAILJET_INCOMPLETE_INFO") );
            }*/

            $data ['username'] = $pre_data->apiKey;
            $data ['password'] = $pre_data->apiSecret;

            return $data;
		}
        /*else{
            JError::raiseWarning( 100, JText::_("COM_MAILJET_NO_DATAFILE") );
        }*/
    }
}
com_mailjet/controller.php000060400000001615152453734450011736 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.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');
}

class MailjetController extends JControllerLegacy {

    function save() {
        global $result;

        $model = $this->getModel();

        $result = $model->store();
        if ($result != false) {
          $this->display();
        } else {
          header('HTTP/1.0 404 Not Found');
        }
    }
}
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.php000060400000002230152453734450011551 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;

/**
 * Base controller class for Fields Component.
 *
 * @since  3.7.0
 */
class FieldsController extends JControllerLegacy
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *                          Recognized key values include 'name', 'default_task', 'model_path', and
	 *                          'view_path' (this list is not meant to be comprehensive).
	 *
	 * @since   3.7.0
	 */
	public function __construct($config = array())
	{
		$this->input = JFactory::getApplication()->input;

		// Frontpage Editor Fields Button proxying:
		if ($this->input->get('view') === 'fields' && $this->input->get('layout') === 'modal')
		{
			// Load the backend language file.
			$lang = JFactory::getLanguage();
			$lang->load('com_fields', JPATH_ADMINISTRATOR);

			$config['base_path'] = JPATH_COMPONENT_ADMINISTRATOR;
		}

		parent::__construct($config);
	}
}
com_fields/models/forms/filter_fields.xml000060400000005403152453734450014630 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset name="group"
		addfieldpath="/administrator/components/com_fields/models/fields">
		<field
			name="context"
			type="fieldcontexts"
			onchange="this.form.submit();"
		/>
	</fieldset>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label=""
			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.php000060400000001771152453734450010645 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;

JLoader::register('FieldsHelper', JPATH_ADMINISTRATOR . '/components/com_fields/helpers/fields.php');

$input   = JFactory::getApplication()->input;
$context = JFactory::getApplication()->getUserStateFromRequest('com_fields.fields.context', 'context', 'com_content.article', 'CMD');
$parts   = FieldsHelper::extract($context);

if ($input->get('view') === 'fields' && $input->get('layout') === 'modal')
{
	if (!JFactory::getUser()->authorise('core.create', $parts[0])
		|| !JFactory::getUser()->authorise('core.edit', $parts[0]))
	{
		JFactory::getApplication()->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');

		return;
	}
}

$controller = JControllerLegacy::getInstance('Fields');
$controller->execute($input->get('task'));
$controller->redirect();
index.html000060400000000037152453734450006551 0ustar00<!DOCTYPE html><title></title>
com_acymailing/acymailing.php000060400000005435152453734450012364 0ustar00<?php
/**
 * @package	AcyMailing for Joomla!
 * @version	5.9.6
 * @author	acyba.com
 * @copyright	(C) 2009-2018 ACYBA S.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.controller');
jimport('joomla.application.component.view');

include_once(rtrim(JPATH_ADMINISTRATOR, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.'components'.DIRECTORY_SEPARATOR.'com_acymailing'.DIRECTORY_SEPARATOR.'helpers'.DIRECTORY_SEPARATOR.'helper.php');

if(acymailing_isDebug()) acymailing_displayErrors();

$view = acymailing_getVar('cmd', 'view');
if(!empty($view) AND !acymailing_getVar('cmd', 'ctrl')){
	acymailing_setVar('ctrl', $view);
	$layout = acymailing_getVar('cmd', 'layout');
	if(!empty($layout)){
		acymailing_setVar('task', $layout);
	}
}
$taskGroup = acymailing_getVar('cmd', 'ctrl', acymailing_getVar('cmd', 'gtask', 'lists'));

global $Itemid;
if(empty($Itemid)){
	$urlItemid = acymailing_getVar('int', 'Itemid');
	if(!empty($urlItemid)) $Itemid = $urlItemid;
}


$config = acymailing_config();

acymailing_addScript(false, ACYMAILING_JS.'acymailing.js?v='.str_replace('.', '', $config->get('version')));

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);
}

$cssFrontend = $config->get('css_frontend', 'default');
if(!empty($cssFrontend)){
	acymailing_addStyle(false, ACYMAILING_CSS.'component_'.$cssFrontend.'.css?v='.filemtime(ACYMAILING_MEDIA.'css'.DS.'component_'.$cssFrontend.'.css'));
}

if($taskGroup == 'newsletter') $taskGroup = 'frontnewsletter';

if(!file_exists(ACYMAILING_CONTROLLER_FRONT.$taskGroup.'.php') || !include(ACYMAILING_CONTROLLER_FRONT.$taskGroup.'.php')){
	return acymailing_raiseError(E_ERROR, 404, 'Page not found : '.$taskGroup);
}

$className = ucfirst($taskGroup).'Controller';
$classGroup = new $className();
acymailing_setVar('view', $classGroup->getName());

$action = acymailing_getVar('cmd', 'task');
if(empty($action)){
	$action = acymailing_getVar('cmd', 'defaulttask');
	acymailing_setVar('task', $action);
}

$classGroup->execute($action);
$classGroup->redirect();
if(acymailing_getVar('string', 'tmpl') !== 'component' && !in_array(acymailing_getVar('cmd', 'task'), array('unsub', 'saveunsub', 'optout', 'out', 'view'))){
	echo acymailing_footer();
}
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.php000060400000003767152453734450013761 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 StatsController extends acymailingController{

	function listing(){
		JRequest::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();

		JPluginHelper::importPlugin('acymailing');
		$this->dispatcher = JDispatcher::getInstance();
		$results = $this->dispatcher->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;
	}

	function detecttimeout(){

		$config = acymailing_config();
		if($config->get('security_key') != JRequest::getString('seckey')) die('wrong key');

		$db = JFactory::getDBO();
		$db->setQuery("REPLACE INTO `#__acymailing_config` (`namekey`,`value`) VALUES ('max_execution_time','5'), ('last_maxexec_check','".time()."')");
		$db->query();

		@ini_set('max_execution_time',600);
		@ignore_user_abort(true);

		$i = 0;
		while($i < 480){
			sleep(8);
			$i += 10;
			$db->setQuery("UPDATE `#__acymailing_config` SET `value` = '".intval($i)."' WHERE `namekey` = 'max_execution_time'");
			$db->query();
			$db->setQuery("UPDATE `#__acymailing_config` SET `value` = '".time()."' WHERE `namekey` = 'last_maxexec_check'");
			$db->query();
			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.php000060400000005624152453734450011562 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 Controller
 *
 * @since  1.5
 */
class SearchController extends JControllerLegacy
{
	/**
	 * Method to display a view.
	 *
	 * @param   bool  $cachable   If true, the view output will be cached
	 * @param   bool  $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 = false)
	{
		// Force it to be the search view
		$this->input->set('view', 'search');

		return parent::display($cachable, $urlparams);
	}

	/**
	 * Search
	 *
	 * @return void
	 *
	 * @throws Exception
	 */
	public function search()
	{
		// Slashes cause errors, <> get stripped anyway later on. # causes problems.
		$badchars = array('#', '>', '<', '\\');
		$searchword = trim(str_replace($badchars, '', $this->input->post->getString('searchword')));

		// If searchword enclosed in double quotes, strip quotes and do exact match
		if (substr($searchword, 0, 1) === '"' && substr($searchword, -1) === '"')
		{
			$post['searchword'] = substr($searchword, 1, -1);
			$this->input->set('searchphrase', 'exact');
		}
		else
		{
			$post['searchword'] = $searchword;
		}

		$post['ordering']     = $this->input->post->getWord('ordering');
		$post['searchphrase'] = $this->input->post->getWord('searchphrase', 'all');
		$post['limit']        = $this->input->post->getUInt('limit');

		if ($post['limit'] === null)
		{
			unset($post['limit']);
		}

		$areas = $this->input->post->get('areas', null, 'array');

		if ($areas)
		{
			foreach ($areas as $area)
			{
				$post['areas'][] = JFilterInput::getInstance()->clean($area, 'cmd');
			}
		}

		// The Itemid from the request, we will use this if it's a search page or if there is no search page available
		$post['Itemid'] = $this->input->getInt('Itemid');

		// Set Itemid id for links from menu
		$app  = JFactory::getApplication();
		$menu = $app->getMenu();
		$item = $menu->getItem($post['Itemid']);

		// The requested Item is not a search page so we need to find one
		if ($item && ($item->component !== 'com_search' || $item->query['view'] !== 'search'))
		{
			// Get item based on component, not link. link is not reliable.
			$item = $menu->getItems('component', 'com_search', true);

			// If we found a search page, use that.
			if (!empty($item))
			{
				$post['Itemid'] = $item->id;
			}
		}

		unset($post['task'], $post['submit']);

		$uri = JUri::getInstance();
		$uri->setQuery($post);
		$uri->setVar('option', 'com_search');

		$this->setRedirect(JRoute::_('index.php' . $uri->toString(array('query', 'fragment')), false));
	}
}
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.php000060400000000626152453734450010641 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_search
 *
 * @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('Search');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_content/content.php000060400000003140152453734450011245 0ustar00<?php
/**
 * @package     Joomla.Site
 * @subpackage  com_content
 *
 * @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;

JLoader::register('ContentHelperRoute', JPATH_SITE . '/components/com_content/helpers/route.php');
JLoader::register('ContentHelperQuery', JPATH_SITE . '/components/com_content/helpers/query.php');
JLoader::register('ContentHelperAssociation', JPATH_SITE . '/components/com_content/helpers/association.php');

$input = JFactory::getApplication()->input;
$user  = JFactory::getUser();

$checkCreateEdit = ($input->get('view') === 'articles' && $input->get('layout') === 'modal')
	|| ($input->get('view') === 'article' && $input->get('layout') === 'pagebreak');

if ($checkCreateEdit)
{
	// Can create in any category (component permission) or at least in one category
	$canCreateRecords = $user->authorise('core.create', 'com_content')
		|| count($user->getAuthorisedCategories('com_content', 'core.create')) > 0;

	// Instead of checking edit on all records, we can use **same** check as the form editing view
	$values = (array) JFactory::getApplication()->getUserState('com_content.edit.article.id');
	$isEditingRecords = count($values);

	$hasAccess = $canCreateRecords || $isEditingRecords;

	if (!$hasAccess)
	{
		JFactory::getApplication()->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');

		return;
	}
}

$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.php000060400000024631152453734450012511 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\IpHelper;

/**
 * Content Component Article Model
 *
 * @since  1.5
 */
class ContentModelArticle extends JModelItem
{
	/**
	 * Model context string.
	 *
	 * @var        string
	 */
	protected $_context = 'com_content.article';

	/**
	 * 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 state from the request.
		$pk = $app->input->getInt('id');
		$this->setState('article.id', $pk);

		$offset = $app->input->getUInt('limitstart');
		$this->setState('list.offset', $offset);

		// Load the parameters.
		$params = $app->getParams();
		$this->setState('params', $params);

		$user = JFactory::getUser();

		// If $pk is set then authorise on complete asset, else on component only
		$asset = empty($pk) ? 'com_content' : 'com_content.article.' . $pk;

		if ((!$user->authorise('core.edit.state', $asset)) && (!$user->authorise('core.edit', $asset)))
		{
			$this->setState('filter.published', 1);
			$this->setState('filter.archived', 2);
		}

		$this->setState('filter.language', JLanguageMultilang::isEnabled());
	}

	/**
	 * Method to get article data.
	 *
	 * @param   integer  $pk  The id of the article.
	 *
	 * @return  object|boolean|JException  Menu item data object on success, boolean false or JException instance on error
	 */
	public function getItem($pk = null)
	{
		$user = JFactory::getUser();

		$pk = (!empty($pk)) ? $pk : (int) $this->getState('article.id');

		if ($this->_item === null)
		{
			$this->_item = array();
		}

		if (!isset($this->_item[$pk]))
		{
			try
			{
				$db = $this->getDbo();
				$query = $db->getQuery(true)
					->select(
						$this->getState(
							'item.select', 'a.id, a.asset_id, a.title, a.alias, a.introtext, a.fulltext, ' .
							'a.state, a.catid, a.created, a.created_by, a.created_by_alias, ' .
							// Use created if modified is 0
							'CASE WHEN a.modified = ' . $db->quote($db->getNullDate()) . ' THEN a.created ELSE a.modified END as modified, ' .
							'a.modified_by, a.checked_out, a.checked_out_time, a.publish_up, a.publish_down, ' .
							'a.images, a.urls, a.attribs, a.version, a.ordering, ' .
							'a.metakey, a.metadesc, a.access, a.hits, a.metadata, a.featured, a.language, a.xreference'
						)
					);
				$query->from('#__content AS a')
					->where('a.id = ' . (int) $pk);

				// Join on category table.
				$query->select('c.title AS category_title, c.alias AS category_alias, c.access AS category_access')
					->innerJoin('#__categories AS c on c.id = a.catid')
					->where('c.published > 0');

				// Join on user table.
				$query->select('u.name AS author')
					->join('LEFT', '#__users AS u on u.id = a.created_by');

				// Filter by language
				if ($this->getState('filter.language'))
				{
					$query->where('a.language in (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
				}

				// Join over the categories to get parent category titles
				$query->select('parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias')
					->join('LEFT', '#__categories as parent ON parent.id = c.parent_id');

				// Join on voting table
				$query->select('ROUND(v.rating_sum / v.rating_count, 0) AS rating, v.rating_count as rating_count')
					->join('LEFT', '#__content_rating AS v ON a.id = v.content_id');

				if ((!$user->authorise('core.edit.state', 'com_content.article.' . $pk)) && (!$user->authorise('core.edit', 'com_content.article.' . $pk)))
				{
					// 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 published state.
				$published = $this->getState('filter.published');
				$archived = $this->getState('filter.archived');

				if (is_numeric($published))
				{
					$query->where('(a.state = ' . (int) $published . ' OR a.state =' . (int) $archived . ')');
				}

				$db->setQuery($query);

				$data = $db->loadObject();

				if (empty($data))
				{
					return JError::raiseError(404, JText::_('COM_CONTENT_ERROR_ARTICLE_NOT_FOUND'));
				}

				// Check for published state if filter set.
				if ((is_numeric($published) || is_numeric($archived)) && (($data->state != $published) && ($data->state != $archived)))
				{
					return JError::raiseError(404, JText::_('COM_CONTENT_ERROR_ARTICLE_NOT_FOUND'));
				}

				// Convert parameter fields to objects.
				$registry = new Registry($data->attribs);

				$data->params = clone $this->getState('params');
				$data->params->merge($registry);

				$data->metadata = new Registry($data->metadata);

				// Technically guest could edit an article, but lets not check that to improve performance a little.
				if (!$user->get('guest'))
				{
					$userId = $user->get('id');
					$asset = 'com_content.article.' . $data->id;

					// Check general edit permission first.
					if ($user->authorise('core.edit', $asset))
					{
						$data->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 == $data->created_by)
						{
							$data->params->set('access-edit', true);
						}
					}
				}

				// Compute view access permissions.
				if ($access = $this->getState('filter.access'))
				{
					// If the access filter has been set, we already know this user can view.
					$data->params->set('access-view', true);
				}
				else
				{
					// If no access filter is set, the layout takes some responsibility for display of limited information.
					$user = JFactory::getUser();
					$groups = $user->getAuthorisedViewLevels();

					if ($data->catid == 0 || $data->category_access === null)
					{
						$data->params->set('access-view', in_array($data->access, $groups));
					}
					else
					{
						$data->params->set('access-view', in_array($data->access, $groups) && in_array($data->category_access, $groups));
					}
				}

				$this->_item[$pk] = $data;
			}
			catch (Exception $e)
			{
				if ($e->getCode() == 404)
				{
					// Need to go thru the error handler to allow Redirect to work.
					JError::raiseError(404, $e->getMessage());
				}
				else
				{
					$this->setError($e);
					$this->_item[$pk] = false;
				}
			}
		}

		return $this->_item[$pk];
	}

	/**
	 * Increment the hit counter for the article.
	 *
	 * @param   integer  $pk  Optional primary key of the article 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('article.id');

			$table = JTable::getInstance('Content', 'JTable');
			$table->hit($pk);
		}

		return true;
	}

	/**
	 * Save user vote on article
	 *
	 * @param   integer  $pk    Joomla Article Id
	 * @param   integer  $rate  Voting rate
	 *
	 * @return  boolean          Return true on success
	 */
	public function storeVote($pk = 0, $rate = 0)
	{
		if ($rate >= 1 && $rate <= 5 && $pk > 0)
		{
			$userIP = IpHelper::getIp();

			// Initialize variables.
			$db    = $this->getDbo();
			$query = $db->getQuery(true);

			// Create the base select statement.
			$query->select('*')
				->from($db->quoteName('#__content_rating'))
				->where($db->quoteName('content_id') . ' = ' . (int) $pk);

			// Set the query and load the result.
			$db->setQuery($query);

			// Check for a database error.
			try
			{
				$rating = $db->loadObject();
			}
			catch (RuntimeException $e)
			{
				JError::raiseWarning(500, $e->getMessage());

				return false;
			}

			// There are no ratings yet, so lets insert our rating
			if (!$rating)
			{
				$query = $db->getQuery(true);

				// Create the base insert statement.
				$query->insert($db->quoteName('#__content_rating'))
					->columns(array($db->quoteName('content_id'), $db->quoteName('lastip'), $db->quoteName('rating_sum'), $db->quoteName('rating_count')))
					->values((int) $pk . ', ' . $db->quote($userIP) . ',' . (int) $rate . ', 1');

				// Set the query and execute the insert.
				$db->setQuery($query);

				try
				{
					$db->execute();
				}
				catch (RuntimeException $e)
				{
					JError::raiseWarning(500, $e->getMessage());

					return false;
				}
			}
			else
			{
				if ($userIP != $rating->lastip)
				{
					$query = $db->getQuery(true);

					// Create the base update statement.
					$query->update($db->quoteName('#__content_rating'))
						->set($db->quoteName('rating_count') . ' = rating_count + 1')
						->set($db->quoteName('rating_sum') . ' = rating_sum + ' . (int) $rate)
						->set($db->quoteName('lastip') . ' = ' . $db->quote($userIP))
						->where($db->quoteName('content_id') . ' = ' . (int) $pk);

					// Set the query and execute the update.
					$db->setQuery($query);

					try
					{
						$db->execute();
					}
					catch (RuntimeException $e)
					{
						JError::raiseWarning(500, $e->getMessage());

						return false;
					}
				}
				else
				{
					return false;
				}
			}

			$this->cleanCache();

			return true;
		}

		JError::raiseWarning(500, JText::sprintf('COM_CONTENT_INVALID_RATING', $rate), "JModelArticle::storeVote($rate)");

		return false;
	}

	/**
	 * Cleans 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   3.9.9
	 */
	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');
	}
}
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.php000060400000054603152453734450012676 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\String\StringHelper;
use Joomla\Utilities\ArrayHelper;

JLoader::register('ContentHelperAssociation', JPATH_SITE . '/components/com_content/helpers/association.php');

/**
 * This models supports retrieving lists of articles.
 *
 * @since  1.6
 */
class ContentModelArticles 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',
				'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',
				'images', 'a.images',
				'urls', 'a.urls',
				'filter_tag',
			);
		}

		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.0.1
	 */
	protected function populateState($ordering = 'ordering', $direction = 'ASC')
	{
		$app = JFactory::getApplication();

		// List state information
		$value = $app->input->get('limit', $app->get('list_limit', 0), 'uint');
		$this->setState('list.limit', $value);

		$value = $app->input->get('limitstart', 0, 'uint');
		$this->setState('list.start', $value);

		$value = $app->input->get('filter_tag', 0, 'uint');
		$this->setState('filter.tag', $value);

		$orderCol = $app->input->get('filter_order', 'a.ordering');

		if (!in_array($orderCol, $this->filter_fields))
		{
			$orderCol = 'a.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);

		$params = $app->getParams();
		$this->setState('params', $params);
		$user = JFactory::getUser();

		if ((!$user->authorise('core.edit.state', 'com_content')) && (!$user->authorise('core.edit', 'com_content')))
		{
			// Filter on published for those who do not have edit or edit.state rights.
			$this->setState('filter.published', 1);
		}

		$this->setState('filter.language', JLanguageMultilang::isEnabled());

		// Process show_noauth parameter
		if ((!$params->get('show_noauth')) || (!JComponentHelper::getParams('com_content')->get('show_noauth')))
		{
			$this->setState('filter.access', true);
		}
		else
		{
			$this->setState('filter.access', false);
		}

		$this->setState('layout', $app->input->getString('layout'));
	}

	/**
	 * 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 .= ':' . serialize($this->getState('filter.published'));
		$id .= ':' . $this->getState('filter.access');
		$id .= ':' . $this->getState('filter.featured');
		$id .= ':' . serialize($this->getState('filter.article_id'));
		$id .= ':' . $this->getState('filter.article_id.include');
		$id .= ':' . serialize($this->getState('filter.category_id'));
		$id .= ':' . $this->getState('filter.category_id.include');
		$id .= ':' . serialize($this->getState('filter.author_id'));
		$id .= ':' . $this->getState('filter.author_id.include');
		$id .= ':' . serialize($this->getState('filter.author_alias'));
		$id .= ':' . $this->getState('filter.author_alias.include');
		$id .= ':' . $this->getState('filter.date_filtering');
		$id .= ':' . $this->getState('filter.date_field');
		$id .= ':' . $this->getState('filter.start_date_range');
		$id .= ':' . $this->getState('filter.end_date_range');
		$id .= ':' . $this->getState('filter.relative_date');
		$id .= ':' . serialize($this->getState('filter.tag'));

		return parent::getStoreId($id);
	}

	/**
	 * Get the master query for retrieving a list of articles subject to the model state.
	 *
	 * @return  JDatabaseQuery
	 *
	 * @since   1.6
	 */
	protected function getListQuery()
	{
		// Get the current user for authorisation checks
		$user = JFactory::getUser();

		// 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.title, a.alias, a.introtext, a.fulltext, ' .
				'a.checked_out, a.checked_out_time, ' .
				'a.catid, a.created, a.created_by, a.created_by_alias, ' .
				// Published/archived article in archive category is treats as archive article
				// If category is not published then force 0
				'CASE WHEN c.published = 2 AND a.state > 0 THEN 2 WHEN c.published != 1 THEN 0 ELSE a.state END as state,' .
				// Use created if modified is 0
				'CASE WHEN a.modified = ' . $db->quote($db->getNullDate()) . ' THEN a.created ELSE a.modified END as modified, ' .
				'a.modified_by, uam.name as modified_by_name,' .
				// Use created if publish_up is 0
				'CASE WHEN a.publish_up = ' . $db->quote($db->getNullDate()) . ' THEN a.created ELSE a.publish_up END as publish_up,' .
				'a.publish_down, a.images, a.urls, a.attribs, a.metadata, a.metakey, a.metadesc, a.access, ' .
				'a.hits, a.xreference, a.featured, a.language, ' . ' ' . $query->length('a.fulltext') . ' AS readmore, a.ordering'
			)
		);

		$query->from('#__content AS a');

		$params      = $this->getState('params');
		$orderby_sec = $params->get('orderby_sec');

		// Join over the frontpage articles if required.
		if ($this->getState('filter.frontpage'))
		{
			if ($orderby_sec === 'front')
			{
				$query->select('fp.ordering');
				$query->join('INNER', '#__content_frontpage AS fp ON fp.content_id = a.id');
			}
			else
			{
				$query->where('a.featured = 1');
			}
		}
		elseif ($orderby_sec === 'front' || $this->getState('list.ordering') === 'fp.ordering')
		{
			$query->select('fp.ordering');
			$query->join('LEFT', '#__content_frontpage AS fp ON fp.content_id = a.id');
		}

		// Join over the categories.
		$query->select('c.title AS category_title, c.path AS category_route, c.access AS category_access, c.alias AS category_alias')
			->select('c.published, c.published AS parents_published, c.lft')
			->join('LEFT', '#__categories AS c ON c.id = a.catid');

		// 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');

		// Join over the categories to get parent category titles
		$query->select('parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias')
			->join('LEFT', '#__categories as parent ON parent.id = c.parent_id');

		if (JPluginHelper::isEnabled('content', 'vote'))
		{
			// Join on voting table
			$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.
		if ($this->getState('filter.access', true))
		{
			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')')
				->where('c.access IN (' . $groups . ')');
		}

		// Filter by published state
		$published = $this->getState('filter.published');

		if (is_numeric($published) && $published == 2)
		{
			/**
			 * If category is archived then article has to be published or archived.
			 * Or category is published then article has to be archived.
			 */
			$query->where('((c.published = 2 AND a.state > 0) OR (c.published = 1 AND a.state = 2))');
		}
		elseif (is_numeric($published))
		{
			// Category has to be published
			$query->where('c.published = 1 AND a.state = ' . (int) $published);
		}
		elseif (is_array($published))
		{
			$published = ArrayHelper::toInteger($published);
			$published = implode(',', $published);

			// Category has to be published
			$query->where('c.published = 1 AND a.state IN (' . $published . ')');
		}

		// Filter by featured state
		$featured = $this->getState('filter.featured');

		switch ($featured)
		{
			case 'hide':
				$query->where('a.featured = 0');
				break;

			case 'only':
				$query->where('a.featured = 1');
				break;

			case 'show':
			default:
				// Normally we do not discriminate between featured/unfeatured items.
				break;
		}

		// Filter by a single or group of articles.
		$articleId = $this->getState('filter.article_id');

		if (is_numeric($articleId))
		{
			$type = $this->getState('filter.article_id.include', true) ? '= ' : '<> ';
			$query->where('a.id ' . $type . (int) $articleId);
		}
		elseif (is_array($articleId))
		{
			$articleId = ArrayHelper::toInteger($articleId);
			$articleId = implode(',', $articleId);
			$type      = $this->getState('filter.article_id.include', true) ? 'IN' : 'NOT IN';
			$query->where('a.id ' . $type . ' (' . $articleId . ')');
		}

		// Filter by a single or group of categories
		$categoryId = $this->getState('filter.category_id');

		if (is_numeric($categoryId))
		{
			$type = $this->getState('filter.category_id.include', true) ? '= ' : '<> ';

			// Add subcategory check
			$includeSubcategories = $this->getState('filter.subcategories', false);
			$categoryEquals       = 'a.catid ' . $type . (int) $categoryId;

			if ($includeSubcategories)
			{
				$levels = (int) $this->getState('filter.max_category_levels', '1');

				// Create a subquery for the subcategory list
				$subQuery = $db->getQuery(true)
					->select('sub.id')
					->from('#__categories as sub')
					->join('INNER', '#__categories as this ON sub.lft > this.lft AND sub.rgt < this.rgt')
					->where('this.id = ' . (int) $categoryId);

				if ($levels >= 0)
				{
					$subQuery->where('sub.level <= this.level + ' . $levels);
				}

				// Add the subquery to the main query
				$query->where('(' . $categoryEquals . ' OR a.catid IN (' . (string) $subQuery . '))');
			}
			else
			{
				$query->where($categoryEquals);
			}
		}
		elseif (is_array($categoryId) && (count($categoryId) > 0))
		{
			$categoryId = ArrayHelper::toInteger($categoryId);
			$categoryId = implode(',', $categoryId);

			if (!empty($categoryId))
			{
				$type = $this->getState('filter.category_id.include', true) ? 'IN' : 'NOT IN';
				$query->where('a.catid ' . $type . ' (' . $categoryId . ')');
			}
		}

		// Filter by author
		$authorId    = $this->getState('filter.author_id');
		$authorWhere = '';

		if (is_numeric($authorId))
		{
			$type        = $this->getState('filter.author_id.include', true) ? '= ' : '<> ';
			$authorWhere = 'a.created_by ' . $type . (int) $authorId;
		}
		elseif (is_array($authorId))
		{
			$authorId = array_filter($authorId, 'is_numeric');

			if ($authorId)
			{
				$authorId    = implode(',', $authorId);
				$type        = $this->getState('filter.author_id.include', true) ? 'IN' : 'NOT IN';
				$authorWhere = 'a.created_by ' . $type . ' (' . $authorId . ')';
			}
		}

		// Filter by author alias
		$authorAlias      = $this->getState('filter.author_alias');
		$authorAliasWhere = '';

		if (is_string($authorAlias))
		{
			$type             = $this->getState('filter.author_alias.include', true) ? '= ' : '<> ';
			$authorAliasWhere = 'a.created_by_alias ' . $type . $db->quote($authorAlias);
		}
		elseif (is_array($authorAlias))
		{
			$first = current($authorAlias);

			if (!empty($first))
			{
				foreach ($authorAlias as $key => $alias)
				{
					$authorAlias[$key] = $db->quote($alias);
				}

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

				if ($authorAlias)
				{
					$type             = $this->getState('filter.author_alias.include', true) ? 'IN' : 'NOT IN';
					$authorAliasWhere = 'a.created_by_alias ' . $type . ' (' . $authorAlias .
						')';
				}
			}
		}

		if (!empty($authorWhere) && !empty($authorAliasWhere))
		{
			$query->where('(' . $authorWhere . ' OR ' . $authorAliasWhere . ')');
		}
		elseif (empty($authorWhere) && empty($authorAliasWhere))
		{
			// If both are empty we don't want to add to the query
		}
		else
		{
			// One of these is empty, the other is not so we just add both
			$query->where($authorWhere . $authorAliasWhere);
		}

		// Define null and now dates
		$nullDate = $db->quote($db->getNullDate());
		$nowDate  = $db->quote(JFactory::getDate()->toSql());

		// Filter by start and end dates.
		if ((!$user->authorise('core.edit.state', 'com_content')) && (!$user->authorise('core.edit', 'com_content')))
		{
			$query->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')')
				->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')');
		}

		// Filter by Date Range or Relative Date
		$dateFiltering = $this->getState('filter.date_filtering', 'off');
		$dateField     = $this->getState('filter.date_field', 'a.created');

		switch ($dateFiltering)
		{
			case 'range':
				$startDateRange = $db->quote($this->getState('filter.start_date_range', $nullDate));
				$endDateRange   = $db->quote($this->getState('filter.end_date_range', $nullDate));
				$query->where(
					'(' . $dateField . ' >= ' . $startDateRange . ' AND ' . $dateField .
					' <= ' . $endDateRange . ')'
				);
				break;

			case 'relative':
				$relativeDate = (int) $this->getState('filter.relative_date', 0);
				$query->where(
					$dateField . ' >= ' . $query->dateAdd($nowDate, -1 * $relativeDate, 'DAY')
				);
				break;

			case 'off':
			default:
				break;
		}

		// Process the filter for list views with user-entered filters
		if (is_object($params) && ($params->get('filter_field') !== 'hide') && ($filter = $this->getState('list.filter')))
		{
			// Clean filter variable
			$filter      = StringHelper::strtolower($filter);
			$monthFilter = $filter;
			$hitsFilter  = (int) $filter;
			$filter      = $db->quote('%' . $db->escape($filter, true) . '%', false);

			switch ($params->get('filter_field'))
			{
				case 'author':
					$query->where(
						'LOWER( CASE WHEN a.created_by_alias > ' . $db->quote(' ') .
						' THEN a.created_by_alias ELSE ua.name END ) LIKE ' . $filter . ' '
					);
					break;

				case 'hits':
					$query->where('a.hits >= ' . $hitsFilter . ' ');
					break;

				case 'month':
					if ($monthFilter != '')
					{
						$query->where(
							$db->quote(date("Y-m-d", strtotime($monthFilter)) . ' 00:00:00') . ' <= CASE WHEN a.publish_up = ' .
							$db->quote($db->getNullDate()) . ' THEN a.created ELSE a.publish_up END'
						);

						$query->where(
							$db->quote(date("Y-m-t", strtotime($monthFilter)) . ' 23:59:59') . ' >= CASE WHEN a.publish_up = ' .
							$db->quote($db->getNullDate()) . ' THEN a.created ELSE a.publish_up END'
						);
					}
					break;

				case 'title':
				default:
					// Default to 'title' if parameter is not valid
					$query->where('LOWER( a.title ) LIKE ' . $filter);
					break;
			}
		}

		// Filter by language
		if ($this->getState('filter.language'))
		{
			$query->where('a.language IN (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
		}

		// 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->innerJoin('(' . (string) $subQuery . ') AS tagmap ON tagmap.content_item_id = a.id');
			}
		}
		elseif ($tagId)
		{
			$query->innerJoin(
				$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.
		$query->order($this->getState('list.ordering', 'a.ordering') . ' ' . $this->getState('list.direction', 'ASC'));

		return $query;
	}

	/**
	 * Method to get a list of articles.
	 *
	 * Overridden to inject convert the attribs field into a JParameter object.
	 *
	 * @return  mixed  An array of objects on success, false on failure.
	 *
	 * @since   1.6
	 */
	public function getItems()
	{
		$items  = parent::getItems();
		$user   = JFactory::getUser();
		$userId = $user->get('id');
		$guest  = $user->get('guest');
		$groups = $user->getAuthorisedViewLevels();
		$input  = JFactory::getApplication()->input;

		// Get the global params
		$globalParams = JComponentHelper::getParams('com_content', true);

		// Convert the parameter fields into objects.
		foreach ($items as &$item)
		{
			$articleParams = new Registry($item->attribs);

			// Unpack readmore and layout params
			$item->alternative_readmore = $articleParams->get('alternative_readmore');
			$item->layout               = $articleParams->get('layout');

			$item->params = clone $this->getState('params');

			/**
			 * For blogs, article params override menu item params only if menu param = 'use_article'
			 * Otherwise, menu item params control the layout
			 * If menu item is 'use_article' and there is no article param, use global
			 */
			if (($input->getString('layout') === 'blog') || ($input->getString('view') === 'featured')
				|| ($this->getState('params')->get('layout_type') === 'blog'))
			{
				// Create an array of just the params set to 'use_article'
				$menuParamsArray = $this->getState('params')->toArray();
				$articleArray    = array();

				foreach ($menuParamsArray as $key => $value)
				{
					if ($value === 'use_article')
					{
						// If the article has a value, use it
						if ($articleParams->get($key) != '')
						{
							// Get the value from the article
							$articleArray[$key] = $articleParams->get($key);
						}
						else
						{
							// Otherwise, use the global value
							$articleArray[$key] = $globalParams->get($key);
						}
					}
				}

				// Merge the selected article params
				if (count($articleArray) > 0)
				{
					$articleParams = new Registry($articleArray);
					$item->params->merge($articleParams);
				}
			}
			else
			{
				// For non-blog layouts, merge all of the article params
				$item->params->merge($articleParams);
			}

			// Get display date
			switch ($item->params->get('list_show_date'))
			{
				case 'modified':
					$item->displayDate = $item->modified;
					break;

				case 'published':
					$item->displayDate = ($item->publish_up == 0) ? $item->created : $item->publish_up;
					break;

				default:
				case 'created':
					$item->displayDate = $item->created;
					break;
			}

			/**
			 * Compute the asset access permissions.
			 * Technically guest could edit an article, but lets not check that to improve performance a little.
			 */
			if (!$guest)
			{
				$asset = 'com_content.article.' . $item->id;

				// Check general edit permission first.
				if ($user->authorise('core.edit', $asset))
				{
					$item->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 == $item->created_by)
					{
						$item->params->set('access-edit', true);
					}
				}
			}

			$access = $this->getState('filter.access');

			if ($access)
			{
				// If the access filter has been set, we already have only the articles this user can view.
				$item->params->set('access-view', true);
			}
			else
			{
				// If no access filter is set, the layout takes some responsibility for display of limited information.
				if ($item->catid == 0 || $item->category_access === null)
				{
					$item->params->set('access-view', in_array($item->access, $groups));
				}
				else
				{
					$item->params->set('access-view', in_array($item->access, $groups) && in_array($item->category_access, $groups));
				}
			}

			// Some contexts may not use tags data at all, so we allow callers to disable loading tag data
			if ($this->getState('load_tags', $item->params->get('show_tags', '1')))
			{
				$item->tags = new JHelperTags;
				$item->tags->getItemTags('com_content.article', $item->id);
			}

			if ($item->params->get('show_associations'))
			{
				$item->associations = ContentHelperAssociation::displayAssociations($item->id);
			}
		}

		return $items;
	}

	/**
	 * Method to get the starting number of items for the data set.
	 *
	 * @return  integer  The starting number of items available in the data set.
	 *
	 * @since   3.0.1
	 */
	public function getStart()
	{
		return $this->getState('list.start');
	}

	/**
	 * Count Items by Month
	 *
	 * @return  mixed  An array of objects on success, false on failure.
	 *
	 * @since   3.9.0
	 */
	public function countItemsByMonth()
	{
		// Create a new query object.
		$db    = $this->getDbo();
		$query = $db->getQuery(true);

		$query
			->select('DATE(' .
				$query->concatenate(
					array(
						$query->year($query->quoteName('publish_up')),
						$query->quote('-'),
						$query->month($query->quoteName('publish_up')),
						$query->quote('-01')
					)
				) . ') as d'
			)
			->select('COUNT(*) as c')
			->from('(' . $this->getListQuery() . ') as b')
			->group($query->quoteName('d'))
			->order($query->quoteName('d') . ' desc');

		return $db->setQuery($query)->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.xml000060400000007754152453734450015407 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fields name="filter">
		<field
			name="search"
			type="text"
			inputmode="search"
			label="COM_CONTENT_MODAL_FILTER_SEARCH_LABEL"
			description="COM_CONTENT_MODAL_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="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="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="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="category_title ASC">JCATEGORY_ASC</option>
			<option value="category_title DESC">JCATEGORY_DESC</option>
			<option value="association ASC" requires="associations">JASSOCIATIONS_ASC</option>
			<option value="association DESC" requires="associations">JASSOCIATIONS_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="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.id ASC">JGRID_HEADING_ID_ASC</option>
			<option value="a.id DESC">JGRID_HEADING_ID_DESC</option>
			<option value="a.featured ASC">JFEATURED_ASC</option>
			<option value="a.featured DESC">JFEATURED_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"
			label="COM_CONTENT_LIST_LIMIT"
			description="COM_CONTENT_LIST_LIMIT_DESC"
			class="inputbox input-mini"
			default="25"
			onchange="this.form.submit();"
		/>
	</fields>
</form>
com_content/models/forms/article.xml000060400000021022152453734450013637 0ustar00<?xml version="1.0" encoding="utf-8"?>
<form>
	<fieldset addfieldpath="/administrator/components/com_categories/models/fields">
		<field
			name="id"
			type="hidden"
			label="COM_CONTENT_ID_LABEL"
			class="inputbox"
			id="id"
			size="10"
			default="0"
			readonly="true"
		/>

		<field
			name="contenthistory"
			type="contenthistory"
			label="JTOOLBAR_VERSIONS"
			id="contenthistory"
			data-typeAlias="com_content.article"
		/>

		<field
			name="asset_id"
			type="hidden"
			filter="unset"
		/>

		<field
			name="title"
			type="text"
			label="JGLOBAL_TITLE"
			description="JFIELD_TITLE_DESC"
			id="title"
			class="inputbox"
			size="30"
			required="true"
		/>

		<field
			name="alias"
			type="text"
			label="JFIELD_ALIAS_LABEL"
			description="JFIELD_ALIAS_DESC"
			id="alias"
			hint="JFIELD_ALIAS_PLACEHOLDER"
			class="inputbox"
			size="45"
		/>

		<field
			name="articletext"
			type="editor"
			label="CONTENT_TEXT_LABEL"
			description="CONTENT_TEXT_DESC"
			buttons="true"
			class="inputbox"
			filter="JComponentHelper::filterText"
			asset_id="com_content"
		/>

		<field
			name="state"
			type="list"
			label="JSTATUS"
			description="JFIELD_PUBLISHED_DESC"
			id="state"
			class="inputbox"
			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="featured"
			type="list"
			label="JGLOBAL_FIELD_FEATURED_LABEL"
			description="JGLOBAL_FIELD_FEATURED_DESC"
			id="featured"
			class="inputbox"
			default="0"
			>
			<option value="0">JNO</option>
			<option value="1">JYES</option>
		</field>

		<field
			name="catid"
			type="categoryedit"
			label="JCATEGORY"
			description="JFIELD_CATEGORY_DESC"
			id="catid"
			extension="com_content"
			class="inputbox"
			required="true"
		/>

		<field
			name="created"
			type="calendar"
			translateformat="true"
			id="created"
			filter="unset"
		/>

		<field
			name="created_by"
			type="text"
			id="created_by"
			filter="unset"
		/>

		<field
			name="created_by_alias"
			type="text"
			label="JGLOBAL_FIELD_CREATED_BY_ALIAS_LABEL"
			description="JGLOBAL_FIELD_CREATED_BY_ALIAS_DESC"
			id="created_by_alias"
			class="inputbox"
			size="20"
		/>

		<field
			name="note"
			type="text"
			label="COM_CONTENT_FIELD_NOTE_LABEL"
			description="COM_CONTENT_FIELD_NOTE_DESC"
			class="inputbox"
			size="40"
			maxlength="255"
		/>

		<field
			name="version_note"
			type="text"
			label="JGLOBAL_FIELD_VERSION_NOTE_LABEL"
			description="JGLOBAL_FIELD_VERSION_NOTE_DESC"
			class="inputbox"
			maxlength="255"
			size="45"
			labelclass="control-label"
		/>

		<field
			name="publish_up"
			type="calendar"
			label="JGLOBAL_FIELD_PUBLISH_UP_LABEL"
			description="JGLOBAL_FIELD_PUBLISH_UP_DESC"
			id="publish_up"
			class="inputbox"
			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"
			id="publish_down"
			class="inputbox"
			translateformat="true"
			showtime="true"
			size="22"
			filter="user_utc"
		/>

		<field
			name="language"
			type="contentlanguage"
			label="JFIELD_LANGUAGE_LABEL"
			description="JFIELD_LANGUAGE_DESC"
			class="inputbox"
			>
			<option value="*">JALL</option>
		</field>

		<field
			name="tags"
			type="tag"
			label="JTAG"
			description="JTAG_DESC"
			class="inputbox"
			multiple="true"
			size="45"
		/>

		<field
			name="metakey"
			type="textarea"
			label="JFIELD_META_KEYWORDS_LABEL"
			description="JFIELD_META_KEYWORDS_DESC"
			id="metakey"
			class="inputbox"
			rows="5"
			cols="50"
		/>

		<field
			name="metadesc"
			type="textarea"
			label="JFIELD_META_DESCRIPTION_LABEL"
			description="JFIELD_META_DESCRIPTION_DESC"
			id="metadesc"
			class="inputbox"
			rows="5"
			cols="50"
		/>

		<field
			name="access"
			type="accesslevel"
			label="JFIELD_ACCESS_LABEL"
			description="JFIELD_ACCESS_DESC"
			id="access"
			class="inputbox"
			size="1"
		/>

		<field
			name="captcha"
			type="captcha"
			label="COM_CONTENT_CAPTCHA_LABEL"
			description="COM_CONTENT_CAPTCHA_DESC"
			validate="captcha"
			namespace="article"
		/>
	</fieldset>
		<fields name="images">
		<fieldset name="image-intro">
			<field
				name="image_intro"
				type="media"
				label="COM_CONTENT_FIELD_INTRO_LABEL"
				description="COM_CONTENT_FIELD_INTRO_DESC"
			/>

			<field
				name="image_intro_alt"
				type="text"
				label="COM_CONTENT_FIELD_IMAGE_ALT_LABEL"
				description="COM_CONTENT_FIELD_IMAGE_ALT_DESC"
				class="inputbox"
				size="20"
			/>

			<field
				name="image_intro_caption"
				type="text"
				label="COM_CONTENT_FIELD_IMAGE_CAPTION_LABEL"
				description="COM_CONTENT_FIELD_IMAGE_CAPTION_DESC"
				class="inputbox"
				size="20"
			/>

			<field
				name="float_intro"
				type="list"
				label="COM_CONTENT_FLOAT_INTRO_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>
		</fieldset>
		<fieldset name="image-full">
			<field
				name="image_fulltext"
				type="media"
				label="COM_CONTENT_FIELD_FULL_LABEL"
				description="COM_CONTENT_FIELD_FULL_DESC"
			/>

			<field
				name="image_fulltext_alt"
				type="text"
				label="COM_CONTENT_FIELD_IMAGE_ALT_LABEL"
				description="COM_CONTENT_FIELD_IMAGE_ALT_DESC"
				class="inputbox"
				size="20"
			/>

			<field
				name="image_fulltext_caption"
				type="text"
				label="COM_CONTENT_FIELD_IMAGE_CAPTION_LABEL"
				description="COM_CONTENT_FIELD_IMAGE_CAPTION_DESC"
				class="inputbox"
				size="20"
			/>

			<field
				name="float_fulltext"
				type="list"
				label="COM_CONTENT_FLOAT_FULLTEXT_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>
		</fieldset>
	</fields>
	<fields name="urls">
		<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"
			class="inputbox"
			size="20"
		/>

		<field
			name="targeta"
			type="hidden"
		/>

		<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"
			class="inputbox"
			size="20"
		/>

		<field
			name="targetb"
			type="hidden"
		/>

		<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"
			class="inputbox"
			size="20"
		/>

		<field
			name="targetc"
			type="hidden"
		/>
	</fields>
	<fields name="metadata">
		<fieldset
			name="jmetadata"
			label="JGLOBAL_FIELDSET_METADATA_OPTIONS">

				<field
					name="robots"
					type="hidden"
					label="JFIELD_METADATA_ROBOTS_LABEL"
					description="JFIELD_METADATA_ROBOTS_DESC"
					filter="unset"
					labelclass="control-label"
					>
					<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="hidden"
					label="JAUTHOR"
					description="JFIELD_METADATA_AUTHOR_DESC"
					filter="unset"
					size="20"
					labelclass="control-label"
				/>

				<field
					name="rights"
					type="hidden"
					label="JFIELD_META_RIGHTS_LABEL"
					description="JFIELD_META_RIGHTS_DESC"
					filter="unset"
					labelclass="control-label"
				/>

				<field
					name="xreference"
					type="hidden"
					label="COM_CONTENT_FIELD_XREFERENCE_LABEL"
					description="COM_CONTENT_FIELD_XREFERENCE_DESC"
					filter="unset"
					class="inputbox"
					size="20"
					labelclass="control-label"
				/>

		</fieldset>
	</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.php000060400000010543152453734450012662 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;

JLoader::register('ContentModelArticles', __DIR__ . '/articles.php');

/**
 * Frontpage Component Model
 *
 * @since  1.5
 */
class ContentModelFeatured extends ContentModelArticles
{
	/**
	 * Model context string.
	 *
	 * @var		string
	 */
	public $_context = 'com_content.frontpage';

	/**
	 * 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($ordering, $direction);

		$input = JFactory::getApplication()->input;
		$user  = JFactory::getUser();
		$app   = JFactory::getApplication('site');

		// List state information
		$limitstart = $input->getUInt('limitstart', 0);
		$this->setState('list.start', $limitstart);

		$params = $this->state->params;
		$menuParams = new Registry;

		if ($menu = $app->getMenu()->getActive())
		{
			$menuParams->loadString($menu->params);
		}

		$mergedParams = clone $menuParams;
		$mergedParams->merge($params);

		$this->setState('params', $mergedParams);

		$limit = $params->get('num_leading_articles') + $params->get('num_intro_articles') + $params->get('num_links');
		$this->setState('list.limit', $limit);
		$this->setState('list.links', $params->get('num_links'));

		$this->setState('filter.frontpage', true);

		if ((!$user->authorise('core.edit.state', 'com_content')) &&  (!$user->authorise('core.edit', 'com_content')))
		{
			// Filter on published for those who do not have edit or edit.state rights.
			$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);
		}

		// Check for category selection
		if ($params->get('featured_categories') && implode(',', $params->get('featured_categories')) == true)
		{
			$featuredCategories = $params->get('featured_categories');
			$this->setState('filter.frontpage.categories', $featuredCategories);
		}

		$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);

		$this->setState('list.ordering', $primary . $secondary . ', a.created DESC');
		$this->setState('list.direction', '');
	}

	/**
	 * Method to get a list of articles.
	 *
	 * @return  mixed  An array of objects on success, false on failure.
	 */
	public function getItems()
	{
		$params = clone $this->getState('params');
		$limit = $params->get('num_leading_articles') + $params->get('num_intro_articles') + $params->get('num_links');

		if ($limit > 0)
		{
			$this->setState('list.limit', $limit);

			return parent::getItems();
		}

		return array();
	}

	/**
	 * 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.frontpage');

		return parent::getStoreId($id);
	}

	/**
	 * Get the list of items.
	 *
	 * @return  JDatabaseQuery
	 */
	protected function getListQuery()
	{
		// Create a new query object.
		$query = parent::getListQuery();

		// Filter by categories
		$featuredCategories = $this->getState('filter.frontpage.categories');

		if (is_array($featuredCategories) && !in_array('', $featuredCategories))
		{
			$query->where('a.catid IN (' . implode(',', ArrayHelper::toInteger($featuredCategories)) . ')');
		}

		return $query;
	}
}
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.php000060400000024244152453734450014300 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 Article View class for the Content component
 *
 * @since  1.5
 */
class ContentViewArticle extends JViewLegacy
{
	protected $item;

	protected $params;

	protected $print;

	protected $state;

	protected $user;

	/**
	 * 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();
		$user       = JFactory::getUser();
		$dispatcher = JEventDispatcher::getInstance();

		$this->item  = $this->get('Item');
		$this->print = $app->input->getBool('print');
		$this->state = $this->get('State');
		$this->user  = $user;

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

			return false;
		}

		// Create a shortcut for $item.
		$item            = $this->item;
		$item->tagLayout = new JLayoutFile('joomla.content.tags');

		// Add router helpers.
		$item->slug        = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
		$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;
		}

		// TODO: Change based on shownoauth
		$item->readmore_link = JRoute::_(ContentHelperRoute::getArticleRoute($item->slug, $item->catid, $item->language));

		// Merge article params. If this is single-article view, menu params override article params
		// Otherwise, article params override menu item params
		$this->params = $this->state->get('params');
		$active       = $app->getMenu()->getActive();
		$temp         = clone $this->params;

		// Check to see which parameters should take priority
		if ($active)
		{
			$currentLink = $active->link;

			// If the current view is the active item and an article view for this article, then the menu item params take priority
			if (strpos($currentLink, 'view=article') && strpos($currentLink, '&id=' . (string) $item->id))
			{
				// Load layout from active query (in case it is an alternative menu item)
				if (isset($active->query['layout']))
				{
					$this->setLayout($active->query['layout']);
				}
				// Check for alternative layout of article
				elseif ($layout = $item->params->get('article_layout'))
				{
					$this->setLayout($layout);
				}

				// $item->params are the article params, $temp are the menu item params
				// Merge so that the menu item params take priority
				$item->params->merge($temp);
			}
			else
			{
				// Current view is not a single article, so the article params take priority here
				// Merge the menu item params with the article params so that the article params take priority
				$temp->merge($item->params);
				$item->params = $temp;

				// Check for alternative layouts (since we are not in a single-article menu item)
				// Single-article menu item layout takes priority over alt layout for an article
				if ($layout = $item->params->get('article_layout'))
				{
					$this->setLayout($layout);
				}
			}
		}
		else
		{
			// Merge so that article params take priority
			$temp->merge($item->params);
			$item->params = $temp;

			// Check for alternative layouts (since we are not in a single-article menu item)
			// Single-article menu item layout takes priority over alt layout for an article
			if ($layout = $item->params->get('article_layout'))
			{
				$this->setLayout($layout);
			}
		}

		$offset = $this->state->get('list.offset');

		// Check the view access to the article (the model has already computed the values).
		if ($item->params->get('access-view') == false && ($item->params->get('show_noauth', '0') == '0'))
		{
			$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
			$app->setHeader('status', 403, true);

			return;
		}

		/**
		 * Check for no 'access-view' and empty fulltext,
		 * - Redirect guest users to login
		 * - Deny access to logged users with 403 code
		 * NOTE: we do not recheck for no access-view + show_noauth disabled ... since it was checked above
		 */
		if ($item->params->get('access-view') == false && !strlen($item->fulltext))
		{
			if ($this->user->get('guest'))
			{
				$return = base64_encode(JUri::getInstance());
				$login_url_with_return = JRoute::_('index.php?option=com_users&view=login&return=' . $return);
				$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'notice');
				$app->redirect($login_url_with_return, 403);
			}
			else
			{
				$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
				$app->setHeader('status', 403, true);

				return;
			}
		}

		/**
		 * NOTE: The following code (usually) sets the text to contain the fulltext, but it is the
		 * responsibility of the layout to check 'access-view' and only use "introtext" for guests
		 */
		if ($item->params->get('show_intro', '1') == '1')
		{
			$item->text = $item->introtext . ' ' . $item->fulltext;
		}
		elseif ($item->fulltext)
		{
			$item->text = $item->fulltext;
		}
		else
		{
			$item->text = $item->introtext;
		}

		$item->tags = new JHelperTags;
		$item->tags->getItemTags('com_content.article', $this->item->id);

		if ($item->params->get('show_associations'))
		{
			$item->associations = ContentHelperAssociation::displayAssociations($item->id);
		}

		// Process the content plugins.
		JPluginHelper::importPlugin('content');
		$dispatcher->trigger('onContentPrepare', array ('com_content.article', &$item, &$item->params, $offset));

		$item->event = new stdClass;
		$results = $dispatcher->trigger('onContentAfterTitle', array('com_content.article', &$item, &$item->params, $offset));
		$item->event->afterDisplayTitle = trim(implode("\n", $results));

		$results = $dispatcher->trigger('onContentBeforeDisplay', array('com_content.article', &$item, &$item->params, $offset));
		$item->event->beforeDisplayContent = trim(implode("\n", $results));

		$results = $dispatcher->trigger('onContentAfterDisplay', array('com_content.article', &$item, &$item->params, $offset));
		$item->event->afterDisplayContent = trim(implode("\n", $results));

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($this->item->params->get('pageclass_sfx', ''));

		$this->_prepareDocument();

		parent::display($tpl);
	}

	/**
	 * Prepares the document.
	 *
	 * @return  void
	 */
	protected function _prepareDocument()
	{
		$app     = JFactory::getApplication();
		$menus   = $app->getMenu();
		$pathway = $app->getPathway();
		$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', '');

		$id = (int) @$menu->query['id'];

		// If the menu item does not concern this article
		if ($menu && (!isset($menu->query['option']) || $menu->query['option'] !== 'com_content' || $menu->query['view'] !== 'article'
			|| $id != $this->item->id))
		{
			// If a browser page title is defined, use that, then fall back to the article title if set, then fall back to the page_title option
			$title = $this->item->params->get('article_page_title', $this->item->title ?: $title);

			$path     = array(array('title' => $this->item->title, 'link' => ''));
			$category = JCategories::getInstance('Content')->get($this->item->catid);

			while ($category && (!isset($menu->query['option']) || $menu->query['option'] !== 'com_content' || $menu->query['view'] === 'article'
				|| $id != $category->id) && $category->id !== 'root')
			{
				$path[]   = array('title' => $category->title, 'link' => ContentHelperRoute::getCategoryRoute($category->id));
				$category = $category->getParent();
			}

			$path = array_reverse($path);

			foreach ($path as $item)
			{
				$pathway->addItem($item['title'], $item['link']);
			}
		}

		// 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->item->title;
		}

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

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

		if ($this->item->metakey)
		{
			$this->document->setMetadata('keywords', $this->item->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 ($app->get('MetaAuthor') == '1')
		{
			$author = $this->item->created_by_alias ?: $this->item->author;
			$this->document->setMetaData('author', $author);
		}

		$mdata = $this->item->metadata->toArray();

		foreach ($mdata as $k => $v)
		{
			if ($v)
			{
				$this->document->setMetadata($k, $v);
			}
		}

		// If there is a pagebreak heading or title, add it to the page title
		if (!empty($this->item->page_title))
		{
			$this->item->title = $this->item->title . ' - ' . $this->item->page_title;
			$this->document->setTitle(
				$this->item->page_title . ' - ' . JText::sprintf('PLG_CONTENT_PAGEBREAK_PAGE_NUM', $this->state->get('list.offset') + 1)
			);
		}

		if ($this->print)
		{
			$this->document->setMetaData('robots', 'noindex, nofollow');
		}
	}
}
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.xml000060400000034104152453734450015144 0ustar00<?xml version="1.0" encoding="utf-8"?>
<metadata>
	<layout title="COM_CONTENT_FEATURED_VIEW_DEFAULT_TITLE" option="COM_CONTENT_FEATURED_VIEW_DEFAULT_OPTION">
		<help
			key = "JHELP_MENUS_MENU_ITEM_ARTICLE_FEATURED"
		/>
		<message>
			<![CDATA[COM_CONTENT_CATEGORY_VIEW_FEATURED_DESC]]>
		</message>
	</layout>

	<!-- Add fields to the parameters object for the layout. -->
	<fields name="params">
		<fieldset name="advanced" label="COM_MENUS_LAYOUT_FEATURED_OPTIONS">
			<field
				name="featured_categories"
				type="category"
				label="COM_CONTENT_FEATURED_CATEGORIES_LABEL"
				description="COM_CONTENT_FEATURED_CATEGORIES_DESC"
				extension="com_content"
				multiple="true"
				size="10"
				default=""
		 		>
				<option value="">JOPTION_ALL_CATEGORIES</option>
			</field>

			<field 
				name="layout_type"
				type="hidden"
				default="blog"
			/>

			<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="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="page_subheading"
				type="text"
				label="JGLOBAL_SUBHEADING_LABEL"
				description="JGLOBAL_SUBHEADING_DESC"
				size="20"
			/>

	</fieldset>

	<fieldset name="article" label="COM_CONTENT_ATTRIBS_FIELDSET_LABEL">
			<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="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="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="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/featured/tmpl/default.php000060400000005655152453734450015144 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');

// 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; ?>" itemscope itemtype="https://schema.org/Blog">
<?php if ($this->params->get('show_page_heading') != 0) : ?>
<div class="page-header">
	<h1>
	<?php echo $this->escape($this->params->get('page_heading')); ?>
	</h1>
</div>
<?php endif; ?>
<?php if ($this->params->get('page_subheading')) : ?>
	<h2> 
		<?php echo $this->escape($this->params->get('page_subheading')); ?>
	</h2>
<?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; ?> clearfix"
			itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
			<?php
				$this->item = &$item;
				echo $this->loadTemplate('item');
			?>
		</div>
		<?php
			$leadingcount++;
		?>
	<?php endforeach; ?>
</div>
<?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
		$key = ($key - $leadingcount) + 1;
		$rowcount = (((int) $key - 1) % (int) $this->columns) + 1;
		$row = $counter / $this->columns;

		if ($rowcount === 1) : ?>

		<div class="items-row cols-<?php echo (int) $this->columns; ?> <?php echo 'row-' . $row; ?> row-fluid">
		<?php endif; ?>
			<div class="item column-<?php echo $rowcount; ?><?php echo $item->state == 0 ? ' system-unpublished' : null; ?> span<?php echo round(12 / $this->columns); ?>"
				itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
			<?php
					$this->item = &$item;
					echo $this->loadTemplate('item');
			?>
			</div>
			<?php $counter++; ?>

			<?php if (($rowcount == $this->columns) or ($counter == $introcount)) : ?>

		</div>
		<?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->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; ?>

</div>
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.php000060400000014344152453734450014454 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
{
	protected $state = null;

	protected $item = null;

	protected $items = null;

	protected $pagination = null;

	protected $lead_items = array();

	protected $intro_items = array();

	protected $link_items = array();

	/** @deprecated  4.0 */
	protected $columns = 1;

	/**
	 * 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.
	 */
	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;

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

			return false;
		}

		$params = &$state->params;

		// PREPARE THE DATA

		// Get the metrics for the structural page layout.
		$numLeading = (int) $params->def('num_leading_articles', 1);
		$numIntro   = (int) $params->def('num_intro_articles', 4);

		JPluginHelper::importPlugin('content');

		// Compute the article slugs and prepare introtext (runs content plugins).
		foreach ($items as &$item)
		{
			$item->slug        = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
			$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.featured', &$item, &$item->params, 0));

			// Old plugins: Use processed text as introtext
			$item->introtext = $item->text;

			$results = $dispatcher->trigger('onContentAfterTitle', array('com_content.featured', &$item, &$item->params, 0));
			$item->event->afterDisplayTitle = trim(implode("\n", $results));

			$results = $dispatcher->trigger('onContentBeforeDisplay', array('com_content.featured', &$item, &$item->params, 0));
			$item->event->beforeDisplayContent = trim(implode("\n", $results));

			$results = $dispatcher->trigger('onContentAfterDisplay', array('com_content.featured', &$item, &$item->params, 0));
			$item->event->afterDisplayContent = trim(implode("\n", $results));
		}

		// Preprocess the breakdown of leading, intro and linked articles.
		// This makes it much easier for the designer to just interogate the arrays.
		$max = count($items);

		// The first group is the leading articles.
		$limit = $numLeading;

		for ($i = 0; $i < $limit && $i < $max; $i++)
		{
			$this->lead_items[$i] = &$items[$i];
		}

		// The second group is the intro articles.
		$limit = $numLeading + $numIntro;

		// Order articles across, then down (or single column mode)
		for ($i = $numLeading; $i < $limit && $i < $max; $i++)
		{
			$this->intro_items[$i] = &$items[$i];
		}

		$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);
		}

		// The remainder are the links.
		for ($i = $numLeading + $numIntro; $i < $max; $i++)
		{
			$this->link_items[$i] = &$items[$i];
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', ''));

		$this->params     = &$params;
		$this->items      = &$items;
		$this->pagination = &$pagination;
		$this->user       = &$user;
		$this->db         = JFactory::getDbo();

		$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'));
		}

		// Add feed links
		if ($this->params->get('show_feed_link', 1))
		{
			$link    = '&format=feed&limitstart=';
			$attribs = array('type' => 'application/rss+xml', 'title' => 'RSS 2.0');
			$this->document->addHeadLink(JRoute::_($link . '&type=rss'), 'alternate', 'rel', $attribs);
			$attribs = array('type' => 'application/atom+xml', 'title' => 'Atom 1.0');
			$this->document->addHeadLink(JRoute::_($link . '&type=atom'), 'alternate', 'rel', $attribs);
		}
	}
}
com_content/controller.php000060400000006404152453734450011764 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\Component\ComponentHelper;

/**
 * Content Component Controller
 *
 * @since  1.5
 */
class ContentController extends JControllerLegacy
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 * Recognized key values include 'name', 'default_task', 'model_path', and
	 * 'view_path' (this list is not meant to be comprehensive).
	 *
	 * @since   3.0.1
	 */
	public function __construct($config = array())
	{
		$this->input = JFactory::getApplication()->input;

		// Article frontpage Editor pagebreak proxying:
		if ($this->input->get('view') === 'article' && $this->input->get('layout') === 'pagebreak')
		{
			$config['base_path'] = JPATH_COMPONENT_ADMINISTRATOR;
		}
		// Article frontpage Editor article proxying:
		elseif ($this->input->get('view') === 'articles' && $this->input->get('layout') === 'modal')
		{
			JHtml::_('stylesheet', 'system/adminlist.css', array('version' => 'auto', 'relative' => true));
			$config['base_path'] = JPATH_COMPONENT_ADMINISTRATOR;
		}

		parent::__construct($config);
	}

	/**
	 * 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  JController  This object to support chaining.
	 *
	 * @since   1.5
	 */
	public function display($cachable = false, $urlparams = false)
	{
		$cachable = true;

		/**
		 * Set the default view name and format from the Request.
		 * Note we are using a_id to avoid collisions with the router and the return page.
		 * Frontend is a bit messier than the backend.
		 */
		$id    = $this->input->getInt('a_id');
		$vName = $this->input->getCmd('view', 'categories');
		$this->input->set('view', $vName);

		$user = JFactory::getUser();

		if ($user->get('id')
			|| ($this->input->getMethod() === 'POST'
			&& (($vName === 'category' && $this->input->get('layout') !== 'blog') || $vName === 'archive' )))
		{
			$cachable = false;
		}

		$safeurlparams = array(
			'catid' => 'INT',
			'id' => 'INT',
			'cid' => 'ARRAY',
			'year' => 'INT',
			'month' => 'INT',
			'limit' => 'UINT',
			'limitstart' => 'UINT',
			'showall' => 'INT',
			'return' => 'BASE64',
			'filter' => 'STRING',
			'filter_order' => 'CMD',
			'filter_order_Dir' => 'CMD',
			'filter-search' => 'STRING',
			'print' => 'BOOLEAN',
			'lang' => 'CMD',
			'Itemid' => 'INT');

		// Check for edit form.
		if ($vName === 'form' && !$this->checkEditId('com_content.edit.article', $id))
		{
			// Somehow the person just went to the form - we don't allow that.
			return JError::raiseError(403, JText::sprintf('JLIB_APPLICATION_ERROR_UNHELD_ID', $id));
		}

		if ($vName === 'article')
		{
			// Get/Create the model
			if ($model = $this->getModel($vName))
			{
				if (ComponentHelper::getParams('com_content')->get('record_hits', 1) == 1)
				{
					$model->hit();
				}
			}
		}

		parent::display($cachable, $safeurlparams);

		return $this;
	}
}
com_content/controllers/article.php000060400000023515152453734450013574 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\Utilities\ArrayHelper;

/**
 * Content article class.
 *
 * @since  1.6.0
 */
class ContentControllerArticle extends JControllerForm
{
	/**
	 * The URL view item variable.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $view_item = 'form';

	/**
	 * The URL view list variable.
	 *
	 * @var    string
	 * @since  1.6
	 */
	protected $view_list = 'categories';

	/**
	 * The URL edit variable.
	 *
	 * @var    string
	 * @since  3.2
	 */
	protected $urlVar = 'a.id';

	/**
	 * Method to add a new record.
	 *
	 * @return  mixed  True if the record can be added, an error object if not.
	 *
	 * @since   1.6
	 */
	public function add()
	{
		if (!parent::add())
		{
			// Redirect to the return page.
			$this->setRedirect($this->getReturnPage());

			return;
		}

		// Redirect to the edit screen.
		$this->setRedirect(
			JRoute::_(
				'index.php?option=' . $this->option . '&view=' . $this->view_item . '&a_id=0'
				. $this->getRedirectToItemAppend(), false
			)
		);

		return true;
	}

	/**
	 * 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())
	{
		$user       = JFactory::getUser();
		$categoryId = ArrayHelper::getValue($data, 'catid', $this->input->getInt('catid'), 'int');
		$allow      = null;

		if ($categoryId)
		{
			// If the category has been passed in the data or URL check it.
			$allow = $user->authorise('core.create', 'com_content.category.' . $categoryId);
		}

		if ($allow === null)
		{
			// In the absence 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; default is id.
	 *
	 * @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->get('id') == $record->created_by;
		}

		return false;
	}

	/**
	 * 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 = 'a_id')
	{
		parent::cancel($key);

		$app = JFactory::getApplication();

		// Load the parameters.
		$params = $app->getParams();

		$customCancelRedir = (bool) $params->get('custom_cancel_redirect');

		if ($customCancelRedir)
		{
			$cancelMenuitemId = (int) $params->get('cancel_redirect_menuitem');

			if ($cancelMenuitemId > 0)
			{
				$item = $app->getMenu()->getItem($cancelMenuitemId);
				$lang = '';

				if (JLanguageMultilang::isEnabled())
				{
					$lang = !is_null($item) && $item->language != '*' ? '&lang=' . $item->language : '';
				}

				// Redirect to the user specified return page.
				$redirlink = $item->link . $lang . '&Itemid=' . $cancelMenuitemId;
			}
			else
			{
				// Redirect to the same article submission form (clean form).
				$redirlink = $app->getMenu()->getActive()->link . '&Itemid=' . $app->getMenu()->getActive()->id;
			}
		}
		else
		{
			$menuitemId = (int) $params->get('redirect_menuitem');
			$lang = '';

			if ($menuitemId > 0)
			{
				$lang = '';
				$item = $app->getMenu()->getItem($menuitemId);

				if (JLanguageMultilang::isEnabled())
				{
					$lang = !is_null($item) && $item->language != '*' ? '&lang=' . $item->language : '';
				}

				// Redirect to the general (redirect_menuitem) user specified return page.
				$redirlink = $item->link . $lang . '&Itemid=' . $menuitemId;
			}
			else
			{
				// Redirect to the return page.
				$redirlink = $this->getReturnPage();
			}
		}

		$this->setRedirect(JRoute::_($redirlink, false));
	}

	/**
	 * 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 = 'a_id')
	{
		$result = parent::edit($key, $urlVar);

		if (!$result)
		{
			$this->setRedirect(JRoute::_($this->getReturnPage(), false));
		}

		return $result;
	}

	/**
	 * 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.5
	 */
	public function getModel($name = 'form', $prefix = '', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, $config);
	}

	/**
	 * 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 = 'a_id')
	{
		// Need to override the parent method completely.
		$tmpl   = $this->input->get('tmpl');

		$append = '';

		// Setup redirect info.
		if ($tmpl)
		{
			$append .= '&tmpl=' . $tmpl;
		}

		// TODO This is a bandaid, not a long term solution.
		/**
		 * if ($layout)
		 * {
		 *	$append .= '&layout=' . $layout;
		 * }
		 */

		$append .= '&layout=edit';

		if ($recordId)
		{
			$append .= '&' . $urlVar . '=' . $recordId;
		}

		$itemId = $this->input->getInt('Itemid');
		$return = $this->getReturnPage();
		$catId  = $this->input->getInt('catid');

		if ($itemId)
		{
			$append .= '&Itemid=' . $itemId;
		}

		if ($catId)
		{
			$append .= '&catid=' . $catId;
		}

		if ($return)
		{
			$append .= '&return=' . base64_encode($return);
		}

		return $append;
	}

	/**
	 * Get the return URL.
	 *
	 * If a "return" variable has been passed in the request
	 *
	 * @return  string	The return URL.
	 *
	 * @since   1.6
	 */
	protected function getReturnPage()
	{
		$return = $this->input->get('return', null, 'base64');

		if (empty($return) || !JUri::isInternal(base64_decode($return)))
		{
			return JUri::base();
		}
		else
		{
			return base64_decode($return);
		}
	}

	/**
	 * 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 = 'a_id')
	{
		$result    = parent::save($key, $urlVar);
		$app       = JFactory::getApplication();
		$articleId = $app->input->getInt('a_id');

		// Load the parameters.
		$params   = $app->getParams();
		$menuitem = (int) $params->get('redirect_menuitem');

		// Check for redirection after submission when creating a new article only
		if ($menuitem > 0 && $articleId == 0)
		{
			$lang = '';

			if (JLanguageMultilang::isEnabled())
			{
				$item = $app->getMenu()->getItem($menuitem);
				$lang = !is_null($item) && $item->language != '*' ? '&lang=' . $item->language : '';
			}

			// If ok, redirect to the return page.
			if ($result)
			{
				$this->setRedirect(JRoute::_('index.php?Itemid=' . $menuitem . $lang, false));
			}
		}
		else
		{
			// If ok, redirect to the return page.
			if ($result)
			{
				$this->setRedirect(JRoute::_($this->getReturnPage(), false));
			}
		}

		return $result;
	}

	/**
	 * Method to reload 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  void
	 *
	 * @since   3.8.0
	 */
	public function reload($key = null, $urlVar = 'a_id')
	{
		return parent::reload($key, $urlVar);
	}

	/**
	 * Method to save a vote.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function vote()
	{
		// Check for request forgeries.
		$this->checkToken();

		$user_rating = $this->input->getInt('user_rating', -1);

		if ($user_rating > -1)
		{
			$url = $this->input->getString('url', '');
			$id = $this->input->getInt('id', 0);
			$viewName = $this->input->getString('view', $this->default_view);
			$model = $this->getModel($viewName);

			// Don't redirect to an external URL.
			if (!JUri::isInternal($url))
			{
				$url = JRoute::_('index.php');
			}

			if ($model->storeVote($id, $user_rating))
			{
				$this->setRedirect($url, JText::_('COM_CONTENT_ARTICLE_VOTE_SUCCESS'));
			}
			else
			{
				$this->setRedirect($url, JText::_('COM_CONTENT_ARTICLE_VOTE_FAILURE'));
			}
		}
	}
}
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.php000060400000001536152453734450011216 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

JLoader::register('ContactHelperRoute', JPATH_COMPONENT . '/helpers/route.php');

$input = JFactory::getApplication()->input;

if ($input->get('view') === 'contacts' && $input->get('layout') === 'modal')
{
	if (!JFactory::getUser()->authorise('core.create', 'com_contact'))
	{
		JFactory::getApplication()->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'warning');

		return;
	}

	JFactory::getLanguage()->load('com_contact', JPATH_ADMINISTRATOR);
}

$controller = JControllerLegacy::getInstance('Contact');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_contact/controllers/contact.php000060400000016561152453734450013570 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;

/**
 * Controller for single contact view
 *
 * @since  1.5.19
 */
class ContactControllerContact extends JControllerForm
{
	/**
	 * 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.4
	 */
	public function getModel($name = '', $prefix = '', $config = array('ignore_request' => true))
	{
		return parent::getModel($name, $prefix, array('ignore_request' => false));
	}

	/**
	 * Method to submit the contact form and send an email.
	 *
	 * @return  boolean  True on success sending the email. False on failure.
	 *
	 * @since   1.5.19
	 */
	public function submit()
	{
		// Check for request forgeries.
		$this->checkToken();

		$app    = JFactory::getApplication();
		$model  = $this->getModel('contact');
		$stub   = $this->input->getString('id');
		$id     = (int) $stub;

		// Get the data from POST
		$data = $this->input->post->get('jform', array(), 'array');

		// Get item
		$model->setState('filter.published', 1);
		$contact = $model->getItem($id);

		// Get item params, take menu parameters into account if necessary
		$active = $app->getMenu()->getActive();
		$stateParams = clone $model->getState()->get('params');

		// If the current view is the active item and a contact view for this contact, then the menu item params take priority
		if ($active && strpos($active->link, 'view=contact') && strpos($active->link, '&id=' . (int) $contact->id))
		{
			// $item->params are the contact params, $temp are the menu item params
			// Merge so that the menu item params take priority
			$contact->params->merge($stateParams);
		}
		else
		{
			// Current view is not a single contact, so the contact params take priority here
			$stateParams->merge($contact->params);
			$contact->params = $stateParams;
		}

		// Check if the contact form is enabled
		if (!$contact->params->get('show_email_form'))
		{
			$this->setRedirect(JRoute::_('index.php?option=com_contact&view=contact&id=' . $stub . '&catid=' . $contact->catid, false));

			return false;
		}

		// Check for a valid session cookie
		if ($contact->params->get('validate_session', 0))
		{
			if (JFactory::getSession()->getState() !== 'active')
			{
				JError::raiseWarning(403, JText::_('JLIB_ENVIRONMENT_SESSION_INVALID'));

				// Save the data in the session.
				$app->setUserState('com_contact.contact.data', $data);

				// Redirect back to the contact form.
				$this->setRedirect(JRoute::_('index.php?option=com_contact&view=contact&id=' . $stub . '&catid=' . $contact->catid, false));

				return false;
			}
		}

		// Contact plugins
		JPluginHelper::importPlugin('contact');
		$dispatcher = JEventDispatcher::getInstance();

		// 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');
			}

			$app->setUserState('com_contact.contact.data', $data);

			$this->setRedirect(JRoute::_('index.php?option=com_contact&view=contact&id=' . $stub . '&catid=' . $contact->catid, false));

			return false;
		}

		// Validation succeeded, continue with custom handlers
		$results = $dispatcher->trigger('onValidateContact', array(&$contact, &$data));

		foreach ($results as $result)
		{
			if ($result instanceof Exception)
			{
				return false;
			}
		}

		// Passed Validation: Process the contact plugins to integrate with other applications
		$dispatcher->trigger('onSubmitContact', array(&$contact, &$data));

		// Send the email
		$sent = false;

		if (!$contact->params->get('custom_reply'))
		{
			$sent = $this->_sendEmail($data, $contact, $contact->params->get('show_email_copy', 0));
		}

		// Set the success message if it was a success
		if (!($sent instanceof Exception))
		{
			$msg = JText::_('COM_CONTACT_EMAIL_THANKS');
		}
		else
		{
			$msg = '';
		}

		// Flush the data from the session
		$app->setUserState('com_contact.contact.data', null);

		// Redirect if it is set in the parameters, otherwise redirect back to where we came from
		if ($contact->params->get('redirect'))
		{
			$this->setRedirect($contact->params->get('redirect'), $msg);
		}
		else
		{
			$this->setRedirect(JRoute::_('index.php?option=com_contact&view=contact&id=' . $stub . '&catid=' . $contact->catid, false), $msg);
		}

		return true;
	}

	/**
	 * Method to get a model object, loading it if required.
	 *
	 * @param   array     $data               The data to send in the email.
	 * @param   stdClass  $contact            The user information to send the email to
	 * @param   boolean   $emailCopyToSender  True to send a copy of the email to the user.
	 *
	 * @return  boolean  True on success sending the email, false on failure.
	 *
	 * @since   1.6.4
	 */
	private function _sendEmail($data, $contact, $emailCopyToSender)
	{
		$app = JFactory::getApplication();

		if ($contact->email_to == '' && $contact->user_id != 0)
		{
			$contact_user      = JUser::getInstance($contact->user_id);
			$contact->email_to = $contact_user->get('email');
		}

		$mailfrom = $app->get('mailfrom');
		$fromname = $app->get('fromname');
		$sitename = $app->get('sitename');

		$name    = $data['contact_name'];
		$email   = JStringPunycode::emailToPunycode($data['contact_email']);
		$subject = $data['contact_subject'];
		$body    = $data['contact_message'];

		// Prepare email body
		$prefix = JText::sprintf('COM_CONTACT_ENQUIRY_TEXT', JUri::base());
		$body   = $prefix . "\n" . $name . ' <' . $email . '>' . "\r\n\r\n" . stripslashes($body);

		// Load the custom fields
		if (!empty($data['com_fields']) && $fields = FieldsHelper::getFields('com_contact.mail', $contact, true, $data['com_fields']))
		{
			$output = FieldsHelper::render(
				'com_contact.mail',
				'fields.render',
				array(
					'context' => 'com_contact.mail',
					'item'    => $contact,
					'fields'  => $fields,
				)
			);

			if ($output)
			{
				$body .= "\r\n\r\n" . $output;
			}
		}

		$mail = JFactory::getMailer();
		$mail->addRecipient($contact->email_to);
		$mail->addReplyTo($email, $name);
		$mail->setSender(array($mailfrom, $fromname));
		$mail->setSubject($sitename . ': ' . $subject);
		$mail->setBody($body);
		$sent = $mail->Send();

		// If we are supposed to copy the sender, do so.

		// Check whether email copy function activated
		if ($emailCopyToSender == true && !empty($data['contact_email_copy']))
		{
			$copytext    = JText::sprintf('COM_CONTACT_COPYTEXT_OF', $contact->name, $sitename);
			$copytext    .= "\r\n\r\n" . $body;
			$copysubject = JText::sprintf('COM_CONTACT_COPYSUBJECT_OF', $subject);

			$mail = JFactory::getMailer();
			$mail->addRecipient($email);
			$mail->addReplyTo($email, $name);
			$mail->setSender(array($mailfrom, $fromname));
			$mail->setSubject($copysubject);
			$mail->setBody($copytext);
			$sent = $mail->Send();
		}

		return $sent;
	}
}
com_contact/models/forms/filter_contacts.xml000060400000007204152453734460015367 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.xml000060400000003343152453734460013637 0ustar00<?xml version="1.0" encoding="UTF-8"?>
<form>
	<fieldset name="contact" addrulepath="components/com_contact/models/rules" label="COM_CONTACT_CONTACT_DEFAULT_LABEL">
		<field
			name="spacer"
			type="spacer"
			label="COM_CONTACT_CONTACT_REQUIRED"
			class="text"
		/>

		<field
			name="contact_name"
			type="text"
			label="COM_CONTACT_CONTACT_EMAIL_NAME_LABEL"
			description="COM_CONTACT_CONTACT_EMAIL_NAME_DESC"
			id="contact-name"
			size="30"
			filter="string"
			required="true"
		/>

		<field
			name="contact_email"
			type="email"
			label="COM_CONTACT_EMAIL_LABEL"
			description="COM_CONTACT_EMAIL_DESC"
			id="contact-email"
			size="30"
			filter="string"
			validate="contactemail"
			autocomplete="email"
			required="true"
		/>

		<field
			name="contact_subject"
			type="text"
			label="COM_CONTACT_CONTACT_MESSAGE_SUBJECT_LABEL"
			description="COM_CONTACT_CONTACT_MESSAGE_SUBJECT_DESC"
			id="contact-emailmsg"
			size="60"
			filter="string"
			validate="contactemailsubject"
			required="true"
		/>

		<field
			name="contact_message"
			type="textarea"
			label="COM_CONTACT_CONTACT_ENTER_MESSAGE_LABEL"
			description="COM_CONTACT_CONTACT_ENTER_MESSAGE_DESC"
			cols="50"
			rows="10"
			id="contact-message"
			filter="safehtml"
			validate="contactemailmessage"
			required="true"
		/>

		<field
			name="contact_email_copy"
			type="checkbox"
			label="COM_CONTACT_CONTACT_EMAIL_A_COPY_LABEL"
			description="COM_CONTACT_CONTACT_EMAIL_A_COPY_DESC"
			id="contact-email-copy"
			default="0"
		/>
	</fieldset>

	<fieldset name="captcha">
		<field
			name="captcha"
			type="captcha"
			label="COM_CONTACT_CAPTCHA_LABEL"
			description="COM_CONTACT_CAPTCHA_DESC"
			validate="captcha"
			namespace="contact"
		/>
	</fieldset>
</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.php000060400000045057152453734460012510 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 ContactModelContact extends JModelForm
{
	/**
	 * The name of the view for a single item
	 *
	 * @since   1.6
	 */
	protected $view_item = 'contact';

	/**
	 * A loaded item
	 *
	 * @since   1.6
	 */
	protected $_item = null;

	/**
	 * Model context string.
	 *
	 * @var		string
	 */
	protected $_context = 'com_contact.contact';

	/**
	 * 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();

		$this->setState('contact.id', $app->input->getInt('id'));
		$this->setState('params', $app->getParams());

		$user = JFactory::getUser();

		if ((!$user->authorise('core.edit.state', 'com_contact')) &&  (!$user->authorise('core.edit', 'com_contact')))
		{
			$this->setState('filter.published', 1);
			$this->setState('filter.archived', 2);
		}
	}

	/**
	 * Method to get the contact form.
	 * The base form is loaded from XML and then an event is fired
	 *
	 * @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)
	{
		$form = $this->loadForm('com_contact.contact', 'contact', array('control' => 'jform', 'load_data' => true));

		if (empty($form))
		{
			return false;
		}

		$temp = clone $this->getState('params');

		$contact = $this->_item[$this->getState('contact.id')];

		$active = JFactory::getApplication()->getMenu()->getActive();

		if ($active)
		{
			// If the current view is the active item and a contact view for this contact, then the menu item params take priority
			if (strpos($active->link, 'view=contact') && strpos($active->link, '&id=' . (int) $contact->id))
			{
				// $contact->params are the contact params, $temp are the menu item params
				// Merge so that the menu item params take priority
				$contact->params->merge($temp);
			}
			else
			{
				// Current view is not a single contact, so the contact params take priority here
				// Merge the menu item params with the contact params so that the contact params take priority
				$temp->merge($contact->params);
				$contact->params = $temp;
			}
		}
		else
		{
			// Merge so that contact params take priority
			$temp->merge($contact->params);
			$contact->params = $temp;
		}

		if (!$contact->params->get('show_email_copy', 0))
		{
			$form->removeField('contact_email_copy');
		}

		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.2
	 */
	protected function loadFormData()
	{
		$data = (array) JFactory::getApplication()->getUserState('com_contact.contact.data', array());

		if (empty($data['language']) && JLanguageMultilang::isEnabled())
		{
			$data['language'] = JFactory::getLanguage()->getTag();
		}

		// Add contact id to contact form data, so fields plugin can work properly
		if (empty($data['catid']))
		{
			$data['catid'] = $this->getItem()->catid;
		}

		$this->preprocessData('com_contact.contact', $data);

		return $data;
	}

	/**
	 * Gets a contact
	 *
	 * @param   integer  $pk  Id for the contact
	 *
	 * @return  mixed Object or null
	 *
	 * @since   1.6.0
	 */
	public function &getItem($pk = null)
	{
		$pk = (!empty($pk)) ? $pk : (int) $this->getState('contact.id');

		if ($this->_item === null)
		{
			$this->_item = array();
		}

		if (!isset($this->_item[$pk]))
		{
			try
			{
				$db = $this->getDbo();
				$query = $db->getQuery(true);

				// 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('item.select', 'a.*') . ',' . $case_when . ',' . $case_when1)
					->from('#__contact_details AS a')

					// Join on category table.
					->select('c.title AS category_title, c.alias AS category_alias, c.access AS category_access')
					->join('LEFT', '#__categories AS c on c.id = a.catid')

					// Join over the categories to get parent category titles
					->select('parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias')
					->join('LEFT', '#__categories as parent ON parent.id = c.parent_id')

					->where('a.id = ' . (int) $pk);

				// Filter by start and end dates.
				$nullDate = $db->quote($db->getNullDate());
				$nowDate = $db->quote(JFactory::getDate()->toSql());

				// Filter by published state.
				$published = $this->getState('filter.published');
				$archived = $this->getState('filter.archived');

				if (is_numeric($published))
				{
					$query->where('(a.published = ' . (int) $published . ' OR a.published =' . (int) $archived . ')')
						->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')')
						->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')');
				}

				$db->setQuery($query);
				$data = $db->loadObject();

				if (empty($data))
				{
					JError::raiseError(404, JText::_('COM_CONTACT_ERROR_CONTACT_NOT_FOUND'));
				}

				// Check for published state if filter set.
				if ((is_numeric($published) || is_numeric($archived)) && (($data->published != $published) && ($data->published != $archived)))
				{
					JError::raiseError(404, JText::_('COM_CONTACT_ERROR_CONTACT_NOT_FOUND'));
				}

				/**
				 * In case some entity params have been set to "use global", those are
				 * represented as an empty string and must be "overridden" by merging
				 * the component and / or menu params here.
				 */
				$registry = new Registry($data->params);

				$data->params = clone $this->getState('params');
				$data->params->merge($registry);

				$registry = new Registry($data->metadata);
				$data->metadata = $registry;

				// Some contexts may not use tags data at all, so we allow callers to disable loading tag data
				if ($this->getState('load_tags', true))
				{
					$data->tags = new JHelperTags;
					$data->tags->getItemTags('com_contact.contact', $data->id);
				}

				// Compute access permissions.
				if (($access = $this->getState('filter.access')))
				{
					// If the access filter has been set, we already know this user can view.
					$data->params->set('access-view', true);
				}
				else
				{
					// If no access filter is set, the layout takes some responsibility for display of limited information.
					$user = JFactory::getUser();
					$groups = $user->getAuthorisedViewLevels();

					if ($data->catid == 0 || $data->category_access === null)
					{
						$data->params->set('access-view', in_array($data->access, $groups));
					}
					else
					{
						$data->params->set('access-view', in_array($data->access, $groups) && in_array($data->category_access, $groups));
					}
				}

				$this->_item[$pk] = $data;
			}
			catch (Exception $e)
			{
				$this->setError($e);
				$this->_item[$pk] = false;
			}
		}

		if ($this->_item[$pk])
		{
			$this->buildContactExtendedData($this->_item[$pk]);
		}

		return $this->_item[$pk];
	}

	/**
	 * Load extended data (profile, articles) for a contact
	 *
	 * @param   object  $contact  The contact object
	 *
	 * @return  void
	 */
	protected function buildContactExtendedData($contact)
	{
		$db        = $this->getDbo();
		$nullDate  = $db->quote($db->getNullDate());
		$nowDate   = $db->quote(JFactory::getDate()->toSql());
		$user      = JFactory::getUser();
		$groups    = implode(',', $user->getAuthorisedViewLevels());
		$published = $this->getState('filter.published');

		// If we are showing a contact list, then the contact parameters take priority
		// So merge the contact parameters with the merged parameters
		if ($this->getState('params')->get('show_contact_list'))
		{
			$this->getState('params')->merge($contact->params);
		}

		// Get the com_content articles by the linked user
		if ((int) $contact->user_id && $this->getState('params')->get('show_articles'))
		{
			$query = $db->getQuery(true)
				->select('a.id')
				->select('a.title')
				->select('a.state')
				->select('a.access')
				->select('a.catid')
				->select('a.created')
				->select('a.language')
				->select('a.publish_up');

			// SQL Server 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';
			$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($case_when1 . ',' . $case_when)
				->from('#__content as a')
				->join('LEFT', '#__categories as c on a.catid=c.id')
				->where('a.created_by = ' . (int) $contact->user_id)
				->where('a.access IN (' . $groups . ')')
				->order('a.publish_up DESC');

			// Filter per language if plugin published
			if (JLanguageMultilang::isEnabled())
			{
				$query->where('a.language IN (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
			}

			if (is_numeric($published))
			{
				$query->where('a.state IN (1,2)')
					->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')')
					->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')');
			}

			// Number of articles to display from config/menu params
			$articles_display_num = $this->getState('params')->get('articles_display_num', 10);

			// Use contact setting?
			if ($articles_display_num === 'use_contact')
			{
				$articles_display_num = $contact->params->get('articles_display_num', 10);

				// Use global?
				if ((string) $articles_display_num === '')
				{
					$articles_display_num = JComponentHelper::getParams('com_contact')->get('articles_display_num', 10);
				}
			}

			$db->setQuery($query, 0, (int) $articles_display_num);
			$articles = $db->loadObjectList();
			$contact->articles = $articles;
		}
		else
		{
			$contact->articles = null;
		}

		// Get the profile information for the linked user
		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_users/models', 'UsersModel');
		$userModel = JModelLegacy::getInstance('User', 'UsersModel', array('ignore_request' => true));
		$data = $userModel->getItem((int) $contact->user_id);

		JPluginHelper::importPlugin('user');

		// Get the form.
		JForm::addFormPath(JPATH_SITE . '/components/com_users/models/forms');
		JForm::addFieldPath(JPATH_SITE . '/components/com_users/models/fields');
		JForm::addFormPath(JPATH_SITE . '/components/com_users/model/form');
		JForm::addFieldPath(JPATH_SITE . '/components/com_users/model/field');

		$form = JForm::getInstance('com_users.profile', 'profile');

		// Get the dispatcher.
		$dispatcher = JEventDispatcher::getInstance();

		// Trigger the form preparation event.
		$dispatcher->trigger('onContentPrepareForm', array($form, $data));

		// Trigger the data preparation event.
		$dispatcher->trigger('onContentPrepareData', array('com_users.profile', $data));

		// Load the data into the form after the plugins have operated.
		$form->bind($data);
		$contact->profile = $form;
	}

	/**
	 * Gets the query to load a contact item
	 *
	 * @param   integer  $pk  The item to be loaded
	 *
	 * @return  mixed    The contact object on success, false on failure
	 *
	 * @throws  Exception  On database failure
	 * @deprecated  4.0    Use ContactModelContact::getItem() instead
	 */
	protected function getContactQuery($pk = null)
	{
		// @todo Cache on the fingerprint of the arguments
		$db       = $this->getDbo();
		$nullDate = $db->quote($db->getNullDate());
		$nowDate  = $db->quote(JFactory::getDate()->toSql());
		$user     = JFactory::getUser();
		$pk       = (!empty($pk)) ? $pk : (int) $this->getState('contact.id');
		$query    = $db->getQuery(true);

		if ($pk)
		{
			// 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';

			$case_when1  = ' CASE WHEN ';
			$case_when1 .= $query->charLength('cc.alias', '!=', '0');
			$case_when1 .= ' THEN ';

			$c_id        = $query->castAsChar('cc.id');
			$case_when1 .= $query->concatenate(array($c_id, 'cc.alias'), ':');
			$case_when1 .= ' ELSE ';
			$case_when1 .= $c_id . ' END as catslug';

			$query->select(
				'a.*, cc.access as category_access, cc.title as category_name, '
				. $case_when . ',' . $case_when1
			)
				->from('#__contact_details AS a')
				->join('INNER', '#__categories AS cc on cc.id = a.catid')
				->where('a.id = ' . (int) $pk);

			$published = $this->getState('filter.published');

			if (is_numeric($published))
			{
				$query->where('a.published IN (1,2)')
					->where('cc.published IN (1,2)');
			}

			$groups = implode(',', $user->getAuthorisedViewLevels());
			$query->where('a.access IN (' . $groups . ')');

			try
			{
				$db->setQuery($query);
				$result = $db->loadObject();

				if (empty($result))
				{
					return false;
				}
			}
			catch (Exception $e)
			{
				$this->setError($e->getMessage());

				return false;
			}

			if ($result)
			{
				$contactParams = new Registry($result->params);

				// If we are showing a contact list, then the contact parameters take priority
				// So merge the contact parameters with the merged parameters
				if ($this->getState('params')->get('show_contact_list'))
				{
					$this->getState('params')->merge($contactParams);
				}

				// Get the com_content articles by the linked user
				if ((int) $result->user_id && $this->getState('params')->get('show_articles'))
				{
					$query = $db->getQuery(true)
						->select('a.id')
						->select('a.title')
						->select('a.state')
						->select('a.access')
						->select('a.catid')
						->select('a.created')
						->select('a.language')
						->select('a.publish_up');

					// SQL Server 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';
					$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($case_when1 . ',' . $case_when)
						->from('#__content as a')
						->join('LEFT', '#__categories as c on a.catid=c.id')
						->where('a.created_by = ' . (int) $result->user_id)
						->where('a.access IN (' . $groups . ')')
						->order('a.publish_up DESC');

					// Filter per language if plugin published
					if (JLanguageMultilang::isEnabled())
					{
						$query->where('a.language IN (' . $db->quote(JFactory::getLanguage()->getTag()) . ',' . $db->quote('*') . ')');
					}

					if (is_numeric($published))
					{
						$query->where('a.state IN (1,2)')
							->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')')
							->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')');
					}

					// Number of articles to display from config/menu params
					$articles_display_num = $this->getState('params')->get('articles_display_num', 10);

					// Use contact setting?
					if ($articles_display_num === 'use_contact')
					{
						$articles_display_num = $contactParams->get('articles_display_num', 10);

						// Use global?
						if ((string) $articles_display_num === '')
						{
							$articles_display_num = JComponentHelper::getParams('com_contact')->get('articles_display_num', 10);
						}
					}

					$db->setQuery($query, 0, (int) $articles_display_num);
					$articles = $db->loadObjectList();
					$result->articles = $articles;
				}
				else
				{
					$result->articles = null;
				}

				// Get the profile information for the linked user
				JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_users/models', 'UsersModel');
				$userModel = JModelLegacy::getInstance('User', 'UsersModel', array('ignore_request' => true));
				$data = $userModel->getItem((int) $result->user_id);

				JPluginHelper::importPlugin('user');
				$form = new JForm('com_users.profile');

				// Get the dispatcher.
				$dispatcher = JEventDispatcher::getInstance();

				// Trigger the form preparation event.
				$dispatcher->trigger('onContentPrepareForm', array($form, $data));

				// Trigger the data preparation event.
				$dispatcher->trigger('onContentPrepareData', array('com_users.profile', $data));

				// Load the data into the form after the plugins have operated.
				$form->bind($data);
				$result->profile = $form;
				$this->contact = $result;

				return $result;
			}
		}

		return false;
	}

	/**
	 * Increment the hit counter for the contact.
	 *
	 * @param   integer  $pk  Optional primary key of the contact to increment.
	 *
	 * @return  boolean  True if successful; false otherwise and internal error set.
	 *
	 * @since   3.0
	 */
	public function hit($pk = 0)
	{
		$input = JFactory::getApplication()->input;
		$hitcount = $input->getInt('hitcount', 1);

		if ($hitcount)
		{
			$pk = (!empty($pk)) ? $pk : (int) $this->getState('contact.id');

			$table = JTable::getInstance('Contact', 'ContactTable');
			$table->hit($pk);
		}

		return true;
	}
}
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.php000060400000034512152453734460014271 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 Contact View class for the Contact component
 *
 * @since  1.5
 */
class ContactViewContact extends JViewLegacy
{
	/**
	 * The item model state
	 *
	 * @var    \Joomla\Registry\Registry
	 * @since  1.6
	 */
	protected $state;

	/**
	 * The form object for the contact item
	 *
	 * @var    JForm
	 * @since  1.6
	 */
	protected $form;

	/**
	 * The item object details
	 *
	 * @var    JObject
	 * @since  1.6
	 */
	protected $item;

	/**
	 * The page to return to on submission
	 *
	 * @var         string
	 * @since       1.6
	 * @deprecated  4.0  Variable not used
	 */
	protected $return_page;

	/**
	 * Should we show a captcha form for the submission of the contact request?
	 *
	 * @var   bool
	 * @since 3.6.3
	 */
	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)
	{
		$app = JFactory::getApplication();
		$user = JFactory::getUser();

		$item = $this->get('Item');
		$state = $this->get('State');
		$contacts = array();

		// Get submitted values
		$data = $app->getUserState('com_contact.contact.data', array());

		// Add catid for selecting custom fields
		$data['catid'] = $item->catid;

		$app->setUserState('com_contact.contact.data', $data);

		$this->form = $this->get('Form');

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

		$temp = clone $params;

		$active = $app->getMenu()->getActive();

		if ($active)
		{
			// If the current view is the active item and a contact view for this contact, then the menu item params take priority
			if (strpos($active->link, 'view=contact') && strpos($active->link, '&id=' . (int) $item->id))
			{
				// $item->params are the contact params, $temp are the menu item params
				// Merge so that the menu item params take priority
				$item->params->merge($temp);
			}
			else
			{
				// Current view is not a single contact, so the contact params take priority here
				// Merge the menu item params with the contact params so that the contact params take priority
				$temp->merge($item->params);
				$item->params = $temp;
			}
		}
		else
		{
			// Merge so that contact params take priority
			$temp->merge($item->params);
			$item->params = $temp;
		}

		// Collect extra contact information when this information is required
		if ($item && $item->params->get('show_contact_list'))
		{
			// Get Category Model data
			$categoryModel = JModelLegacy::getInstance('Category', 'ContactModel', array('ignore_request' => true));

			$categoryModel->setState('category.id', $item->catid);
			$categoryModel->setState('list.ordering', 'a.name');
			$categoryModel->setState('list.direction', 'asc');
			$categoryModel->setState('filter.published', 1);

			$contacts = $categoryModel->getItems();
		}

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

			return false;
		}

		// Check if access is not public
		$groups = $user->getAuthorisedViewLevels();

		$return = '';

		if ((!in_array($item->access, $groups)) || (!in_array($item->category_access, $groups)))
		{
			$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
			$app->setHeader('status', 403, true);

			return false;
		}

		$options['category_id'] = $item->catid;
		$options['order by']    = 'a.default_con DESC, a.ordering ASC';

		/**
		 * Handle email cloaking
		 *
		 * Keep a copy of the raw email address so it can
		 * still be accessed in the layout if needed.
		 */
		$item->email_raw = $item->email_to;

		if ($item->email_to && $item->params->get('show_email'))
		{
			$item->email_to = JHtml::_('email.cloak', $item->email_to, (bool) $item->params->get('add_mailto_link', true));
		}

		if ($item->params->get('show_street_address') || $item->params->get('show_suburb') || $item->params->get('show_state')
			|| $item->params->get('show_postcode') || $item->params->get('show_country'))
		{
			if (!empty($item->address) || !empty($item->suburb) || !empty($item->state) || !empty($item->country) || !empty($item->postcode))
			{
				$item->params->set('address_check', 1);
			}
		}
		else
		{
			$item->params->set('address_check', 0);
		}

		// Manage the display mode for contact detail groups
		switch ($item->params->get('contact_icons'))
		{
			case 1 :
				// Text
				$item->params->set('marker_address',   JText::_('COM_CONTACT_ADDRESS') . ': ');
				$item->params->set('marker_email',     JText::_('JGLOBAL_EMAIL') . ': ');
				$item->params->set('marker_telephone', JText::_('COM_CONTACT_TELEPHONE') . ': ');
				$item->params->set('marker_fax',       JText::_('COM_CONTACT_FAX') . ': ');
				$item->params->set('marker_mobile',    JText::_('COM_CONTACT_MOBILE') . ': ');
				$item->params->set('marker_webpage',   JText::_('COM_CONTACT_WEBPAGE') . ': ');
				$item->params->set('marker_misc',      JText::_('COM_CONTACT_OTHER_INFORMATION') . ': ');
				$item->params->set('marker_class',     'jicons-text');
				break;

			case 2 :
				// None
				$item->params->set('marker_address',   '');
				$item->params->set('marker_email',     '');
				$item->params->set('marker_telephone', '');
				$item->params->set('marker_mobile',    '');
				$item->params->set('marker_webpage',   '');
				$item->params->set('marker_fax',       '');
				$item->params->set('marker_misc',      '');
				$item->params->set('marker_class',     'jicons-none');
				break;

			default :
				if ($item->params->get('icon_address'))
				{
					$image1 = JHtml::_('image', $item->params->get('icon_address', 'con_address.png'), JText::_('COM_CONTACT_ADDRESS') . ': ', null, false);
				}
				else
				{
					$image1 = JHtml::_(
						'image', 'contacts/' . $item->params->get('icon_address', 'con_address.png'), JText::_('COM_CONTACT_ADDRESS') . ': ', null, true
					);
				}

				if ($item->params->get('icon_email'))
				{
					$image2 = JHtml::_('image', $item->params->get('icon_email', 'emailButton.png'), JText::_('JGLOBAL_EMAIL') . ': ', null, false);
				}
				else
				{
					$image2 = JHtml::_('image', 'contacts/' . $item->params->get('icon_email', 'emailButton.png'), JText::_('JGLOBAL_EMAIL') . ': ', null, true);
				}

				if ($item->params->get('icon_telephone'))
				{
					$image3 = JHtml::_('image', $item->params->get('icon_telephone', 'con_tel.png'), JText::_('COM_CONTACT_TELEPHONE') . ': ', null, false);
				}
				else
				{
					$image3 = JHtml::_(
						'image', 'contacts/' . $item->params->get('icon_telephone', 'con_tel.png'), JText::_('COM_CONTACT_TELEPHONE') . ': ', null, true
					);
				}

				if ($item->params->get('icon_fax'))
				{
					$image4 = JHtml::_('image', $item->params->get('icon_fax', 'con_fax.png'), JText::_('COM_CONTACT_FAX') . ': ', null, false);
				}
				else
				{
					$image4 = JHtml::_('image', 'contacts/' . $item->params->get('icon_fax', 'con_fax.png'), JText::_('COM_CONTACT_FAX') . ': ', null, true);
				}

				if ($item->params->get('icon_misc'))
				{
					$image5 = JHtml::_('image', $item->params->get('icon_misc', 'con_info.png'), JText::_('COM_CONTACT_OTHER_INFORMATION') . ': ', null, false);
				}
				else
				{
					$image5 = JHtml::_(
						'image',
						'contacts/' . $item->params->get('icon_misc', 'con_info.png'),
						JText::_('COM_CONTACT_OTHER_INFORMATION') . ': ', null, true
					);
				}

				if ($item->params->get('icon_mobile'))
				{
					$image6 = JHtml::_('image', $item->params->get('icon_mobile', 'con_mobile.png'), JText::_('COM_CONTACT_MOBILE') . ': ', null, false);
				}
				else
				{
					$image6 = JHtml::_(
						'image', 'contacts/' . $item->params->get('icon_mobile', 'con_mobile.png'), JText::_('COM_CONTACT_MOBILE') . ': ', null, true
					);
				}

				$item->params->set('marker_address',   $image1);
				$item->params->set('marker_email',     $image2);
				$item->params->set('marker_telephone', $image3);
				$item->params->set('marker_fax',       $image4);
				$item->params->set('marker_misc',      $image5);
				$item->params->set('marker_mobile',    $image6);
				$item->params->set('marker_webpage',   ' ');
				$item->params->set('marker_class',     'jicons-icons');
				break;
		}

		// Add links to contacts
		if ($item->params->get('show_contact_list') && count($contacts) > 1)
		{
			foreach ($contacts as &$contact)
			{
				$contact->link = JRoute::_(ContactHelperRoute::getContactRoute($contact->slug, $contact->catid), false);
			}

			$item->link = JRoute::_(ContactHelperRoute::getContactRoute($item->slug, $item->catid), false);
		}

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

		$dispatcher	= JEventDispatcher::getInstance();

		$offset = $state->get('list.offset');

		// Fix for where some plugins require a text attribute
		$item->text = null;

		if (!empty($item->misc))
		{
			$item->text = $item->misc;
		}

		$dispatcher->trigger('onContentPrepare', array('com_contact.contact', &$item, &$item->params, $offset));

		// Store the events for later
		$item->event = new stdClass;

		$results = $dispatcher->trigger('onContentAfterTitle', array('com_contact.contact', &$item, &$item->params, $offset));
		$item->event->afterDisplayTitle = trim(implode("\n", $results));

		$results = $dispatcher->trigger('onContentBeforeDisplay', array('com_contact.contact', &$item, &$item->params, $offset));
		$item->event->beforeDisplayContent = trim(implode("\n", $results));

		$results = $dispatcher->trigger('onContentAfterDisplay', array('com_contact.contact', &$item, &$item->params, $offset));
		$item->event->afterDisplayContent = trim(implode("\n", $results));

		if (!empty($item->text))
		{
			$item->misc = $item->text;
		}

		$contactUser = null;

		if ($item->params->get('show_user_custom_fields') && $item->user_id && $contactUser = JFactory::getUser($item->user_id))
		{
			$contactUser->text = '';

			JEventDispatcher::getInstance()->trigger('onContentPrepare', array ('com_users.user', &$contactUser, &$item->params, 0));

			if (!isset($contactUser->jcfields))
			{
				$contactUser->jcfields = array();
			}
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($item->params->get('pageclass_sfx', ''));

		$this->contact     = &$item;
		$this->params      = &$item->params;
		$this->return      = &$return;
		$this->state       = &$state;
		$this->item        = &$item;
		$this->user        = &$user;
		$this->contacts    = &$contacts;
		$this->contactUser = $contactUser;

		// Override the layout only if this is not the active menu item
		// If it is the active menu item, then the view and item id will match
		if ((!$active) || ((strpos($active->link, 'view=contact') === false) || (strpos($active->link, '&id=' . (string) $this->item->id) === false)))
		{
			if (($layout = $item->params->get('contact_layout')))
			{
				$this->setLayout($layout);
			}
		}
		elseif (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']);
		}

		$model = $this->getModel();
		$model->hit();

		$captchaSet = $item->params->get('captcha', JFactory::getApplication()->get('captcha', '0'));

		foreach (JPluginHelper::getPlugin('captcha') as $plugin)
		{
			if ($captchaSet === $plugin->name)
			{
				$this->captchaEnabled = true;
				break;
			}
		}

		$this->_prepareDocument();

		return parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function _prepareDocument()
	{
		$app     = JFactory::getApplication();
		$menus   = $app->getMenu();
		$pathway = $app->getPathway();
		$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', '');

		$id = (int) @$menu->query['id'];

		// If the menu item does not concern this contact
		if ($menu && (!isset($menu->query['option']) || $menu->query['option'] !== 'com_contact' || $menu->query['view'] !== 'contact'
			|| $id != $this->item->id))
		{
			// If this is not a single contact menu item, set the page title to the contact title
			if ($this->item->name)
			{
				$title = $this->item->name;
			}

			$path = array(array('title' => $this->contact->name, 'link' => ''));
			$category = JCategories::getInstance('Contact')->get($this->contact->catid);

			while ($category && (!isset($menu->query['option']) || $menu->query['option'] !== 'com_contact' || $menu->query['view'] === 'contact'
				|| $id != $category->id) && $category->id > 1)
			{
				$path[] = array('title' => $category->title, 'link' => ContactHelperRoute::getCategoryRoute($this->contact->catid));
				$category = $category->getParent();
			}

			$path = array_reverse($path);

			foreach ($path as $item)
			{
				$pathway->addItem($item['title'], $item['link']);
			}
		}

		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->item->name;
		}

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

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

		if ($this->item->metakey)
		{
			$this->document->setMetadata('keywords', $this->item->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'));
		}

		$mdata = $this->item->metadata->toArray();

		foreach ($mdata as $k => $v)
		{
			if ($v)
			{
				$this->document->setMetadata($k, $v);
			}
		}
	}
}
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.php000060400000004243152453734460011745 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;

/**
 * Contact Component Controller
 *
 * @since  1.5
 */
class ContactController extends JControllerLegacy
{
	/**
	 * Constructor.
	 *
	 * @param   array  $config  An optional associative array of configuration settings.
	 *                          Recognized key values include 'name', 'default_task', 'model_path', and
	 *                          'view_path' (this list is not meant to be comprehensive).
	 *
	 * @since   3.7.0
	 */
	public function __construct($config = array())
	{
		$this->input = JFactory::getApplication()->input;

		// Contact frontpage Editor contacts proxying:
		if ($this->input->get('view') === 'contacts' && $this->input->get('layout') === 'modal')
		{
			JHtml::_('stylesheet', 'system/adminlist.css', array(), true);
			$config['base_path'] = JPATH_COMPONENT_ADMINISTRATOR;
		}

		parent::__construct($config);
	}

	/**
	 * 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())
	{
		if (JFactory::getApplication()->getUserState('com_contact.contact.data') === null)
		{
			$cachable = true;
		}

		// Set the default view name and format from the Request.
		$vName = $this->input->get('view', 'categories');
		$this->input->set('view', $vName);

		$safeurlparams = array('catid' => 'INT', 'id' => 'INT', 'cid' => 'ARRAY', 'year' => 'INT', 'month' => 'INT',
			'limit' => 'UINT', 'limitstart' => 'UINT', 'showall' => 'INT', 'return' => 'BASE64', 'filter' => 'STRING',
			'filter_order' => 'CMD', 'filter_order_Dir' => 'CMD', 'filter-search' => 'STRING', 'print' => 'BOOLEAN',
			'lang' => 'CMD');

		parent::display($cachable, $safeurlparams);

		return $this;
	}
}
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.php000060400000012122152453734460013170 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 Newsfeed Model
 *
 * @since  1.5
 */
class NewsfeedsModelNewsfeed extends JModelItem
{
	/**
	 * Model context string.
	 *
	 * @var		string
	 * @since   1.6
	 */
	protected $_context = 'com_newsfeeds.newsfeed';

	/**
	 * 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('site');

		// Load state from the request.
		$pk = $app->input->getInt('id');
		$this->setState('newsfeed.id', $pk);

		$offset = $app->input->get('limitstart', 0, 'uint');
		$this->setState('list.offset', $offset);

		// Load the parameters.
		$params = $app->getParams();
		$this->setState('params', $params);

		$user = JFactory::getUser();

		if ((!$user->authorise('core.edit.state', 'com_newsfeeds')) && (!$user->authorise('core.edit', 'com_newsfeeds')))
		{
			$this->setState('filter.published', 1);
			$this->setState('filter.archived', 2);
		}
	}

	/**
	 * Method to get newsfeed data.
	 *
	 * @param   integer  $pk  The id of the newsfeed.
	 *
	 * @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('newsfeed.id');

		if ($this->_item === null)
		{
			$this->_item = array();
		}

		if (!isset($this->_item[$pk]))
		{
			try
			{
				$db = $this->getDbo();
				$query = $db->getQuery(true)
					->select($this->getState('item.select', 'a.*'))
					->from('#__newsfeeds AS a');

				// Join on category table.
				$query->select('c.title AS category_title, c.alias AS category_alias, c.access AS category_access')
					->join('LEFT', '#__categories AS c on c.id = a.catid');

				// Join on user table.
				$query->select('u.name AS author')
					->join('LEFT', '#__users AS u on u.id = a.created_by');

				// Join over the categories to get parent category titles
				$query->select('parent.title as parent_title, parent.id as parent_id, parent.path as parent_route, parent.alias as parent_alias')
					->join('LEFT', '#__categories as parent ON parent.id = c.parent_id')

					->where('a.id = ' . (int) $pk);

				// Filter by start and end dates.
				$nullDate = $db->quote($db->getNullDate());
				$nowDate = $db->quote(JFactory::getDate()->toSql());

				// Filter by published state.
				$published = $this->getState('filter.published');
				$archived = $this->getState('filter.archived');

				if (is_numeric($published))
				{
					$query->where('(a.published = ' . (int) $published . ' OR a.published =' . (int) $archived . ')')
						->where('(a.publish_up = ' . $nullDate . ' OR a.publish_up <= ' . $nowDate . ')')
						->where('(a.publish_down = ' . $nullDate . ' OR a.publish_down >= ' . $nowDate . ')')
						->where('(c.published = ' . (int) $published . ' OR c.published =' . (int) $archived . ')');
				}

				$db->setQuery($query);

				$data = $db->loadObject();

				if (empty($data))
				{
					JError::raiseError(404, JText::_('COM_NEWSFEEDS_ERROR_FEED_NOT_FOUND'));
				}

				// Check for published state if filter set.

				if ((is_numeric($published) || is_numeric($archived)) && $data->published != $published && $data->published != $archived)
				{
					JError::raiseError(404, JText::_('COM_NEWSFEEDS_ERROR_FEED_NOT_FOUND'));
				}

				// Convert parameter fields to objects.
				$registry = new Registry($data->params);
				$data->params = clone $this->getState('params');
				$data->params->merge($registry);

				$data->metadata = new Registry($data->metadata);

				// Compute access permissions.

				if ($access = $this->getState('filter.access'))
				{
					// If the access filter has been set, we already know this user can view.
					$data->params->set('access-view', true);
				}
				else
				{
					// If no access filter is set, the layout takes some responsibility for display of limited information.
					$user   = JFactory::getUser();
					$groups = $user->getAuthorisedViewLevels();
					$data->params->set('access-view', in_array($data->access, $groups) && in_array($data->category_access, $groups));
				}

				$this->_item[$pk] = $data;
			}
			catch (Exception $e)
			{
				$this->setError($e);
				$this->_item[$pk] = false;
			}
		}

		return $this->_item[$pk];
	}

	/**
	 * Increment the hit counter for the newsfeed.
	 *
	 * @param   int  $pk  Optional primary key of the item to increment.
	 *
	 * @return  boolean  True if successful; false otherwise and internal error set.
	 *
	 * @since   3.0
	 */
	public function hit($pk = 0)
	{
		$input = JFactory::getApplication()->input;
		$hitcount = $input->getInt('hitcount', 1);

		if ($hitcount)
		{
			$pk = (!empty($pk)) ? $pk : (int) $this->getState('newsfeed.id');

			$table = JTable::getInstance('Newsfeed', 'NewsfeedsTable');
			$table->hit($pk);
		}

		return true;
	}
}
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.php000060400000020054152453734460014762 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 NewsfeedsViewNewsfeed extends JViewLegacy
{
	/**
	 * @var     object
	 * @since   1.6
	 */
	protected $state;

	/**
	 * @var     object
	 * @since   1.6
	 */
	protected $item;

	/**
	 * @var     boolean
	 * @since   1.6
	 */
	protected $print;

	/**
	 * 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)
	{
		$app  = JFactory::getApplication();
		$user = JFactory::getUser();

		// Get view related request variables.
		$print = $app->input->getBool('print');

		// Get model data.
		$state = $this->get('State');
		$item  = $this->get('Item');

		// Check for errors.
		// @TODO: Maybe this could go into JComponentHelper::raiseErrors($this->get('Errors'))
		if (count($errors = $this->get('Errors')))
		{
			JError::raiseWarning(500, implode("\n", $errors));

			return false;
		}

		// Add router helpers.
		$item->slug = $item->alias ? ($item->id . ':' . $item->alias) : $item->id;
		$item->catslug = $item->category_alias ? ($item->catid . ':' . $item->category_alias) : $item->catid;
		$item->parent_slug = $item->category_alias ? ($item->parent_id . ':' . $item->parent_alias) : $item->parent_id;

		// Merge newsfeed params. If this is single-newsfeed view, menu params override newsfeed params
		// Otherwise, newsfeed params override menu item params
		$params = $state->get('params');
		$newsfeed_params = clone $item->params;
		$active = $app->getMenu()->getActive();
		$temp = clone $params;

		// Check to see which parameters should take priority
		if ($active)
		{
			$currentLink = $active->link;

			// If the current view is the active item and a newsfeed view for this feed, then the menu item params take priority
			if (strpos($currentLink, 'view=newsfeed') && strpos($currentLink, '&id=' . (string) $item->id))
			{
				// $item->params are the newsfeed params, $temp are the menu item params
				// Merge so that the menu item params take priority
				$newsfeed_params->merge($temp);
				$item->params = $newsfeed_params;

				// Load layout from active query (in case it is an alternative menu item)
				if (isset($active->query['layout']))
				{
					$this->setLayout($active->query['layout']);
				}
			}
			else
			{
				// Current view is not a single newsfeed, so the newsfeed params take priority here
				// Merge the menu item params with the newsfeed params so that the newsfeed params take priority
				$temp->merge($newsfeed_params);
				$item->params = $temp;

				// Check for alternative layouts (since we are not in a single-newsfeed menu item)
				if ($layout = $item->params->get('newsfeed_layout'))
				{
					$this->setLayout($layout);
				}
			}
		}
		else
		{
			// Merge so that newsfeed params take priority
			$temp->merge($newsfeed_params);
			$item->params = $temp;

			// Check for alternative layouts (since we are not in a single-newsfeed menu item)
			if ($layout = $item->params->get('newsfeed_layout'))
			{
				$this->setLayout($layout);
			}
		}

		// Check the access to the newsfeed
		$levels = $user->getAuthorisedViewLevels();

		if (!in_array($item->access, $levels) || (in_array($item->access, $levels) && (!in_array($item->category_access, $levels))))
		{
			$app->enqueueMessage(JText::_('JERROR_ALERTNOAUTHOR'), 'error');
			$app->setHeader('status', 403, true);

			return;
		}

		// Get the current menu item
		$params = $app->getParams();

		// Get the newsfeed
		$newsfeed = $item;

		$params->merge($item->params);

		try
		{
			$feed = new JFeedFactory;
			$this->rssDoc = $feed->getFeed($newsfeed->link);
		}
		catch (InvalidArgumentException $e)
		{
			$msg = JText::_('COM_NEWSFEEDS_ERRORS_FEED_NOT_RETRIEVED');
		}
		catch (RunTimeException $e)
		{
			$msg = JText::_('COM_NEWSFEEDS_ERRORS_FEED_NOT_RETRIEVED');
		}

		if (empty($this->rssDoc))
		{
			$msg = JText::_('COM_NEWSFEEDS_ERRORS_FEED_NOT_RETRIEVED');
		}

		$feed_display_order = $params->get('feed_display_order', 'des');

		if ($feed_display_order === 'asc')
		{
			$this->rssDoc->reverseItems();
		}

		// Escape strings for HTML output
		$this->pageclass_sfx = htmlspecialchars($params->get('pageclass_sfx', ''));

		$this->params = $params;
		$this->newsfeed = $newsfeed;
		$this->state = $state;
		$this->item = $item;
		$this->user = $user;

		if (!empty($msg))
		{
			$this->msg = $msg;
		}

		$this->print = $print;

		$item->tags = new JHelperTags;
		$item->tags->getItemTags('com_newsfeeds.newsfeed', $item->id);

		// Increment the hit counter of the newsfeed.
		$model = $this->getModel();
		$model->hit();

		$this->_prepareDocument();

		return parent::display($tpl);
	}

	/**
	 * Prepares the document
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function _prepareDocument()
	{
		$app     = JFactory::getApplication();
		$menus   = $app->getMenu();
		$pathway = $app->getPathway();
		$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_NEWSFEEDS_DEFAULT_PAGE_TITLE'));
		}

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

		$id = (int) @$menu->query['id'];

		// If the menu item does not concern this newsfeed
		if ($menu && (!isset($menu->query['option']) || $menu->query['option'] !== 'com_newsfeeds' || $menu->query['view'] !== 'newsfeed'
			|| $id != $this->item->id))
		{
			// If this is not a single newsfeed menu item, set the page title to the newsfeed title
			if ($this->item->name)
			{
				$title = $this->item->name;
			}

			$path = array(array('title' => $this->item->name, 'link' => ''));
			$category = JCategories::getInstance('Newsfeeds')->get($this->item->catid);

			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)
			{
				$pathway->addItem($item['title'], $item['link']);
			}
		}

		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->item->name;
		}

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

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

		if ($this->item->metakey)
		{
			$this->document->setMetadata('keywords', $this->item->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 ($app->get('MetaTitle') == '1')
		{
			$this->document->setMetaData('title', $this->item->name);
		}

		if ($app->get('MetaAuthor') == '1')
		{
			$this->document->setMetaData('author', $this->item->author);
		}

		$mdata = $this->item->metadata->toArray();

		foreach ($mdata as $k => $v)
		{
			if ($v)
			{
				$this->document->setMetadata($k, $v);
			}
		}
	}
}
com_newsfeeds/controller.php000060400000002471152453734460012276 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;

/**
 * Newsfeeds Component Controller
 *
 * @since  1.5
 */
class NewsfeedsController extends JControllerLegacy
{
	/**
	 * Method to show a newsfeeds 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 = false)
	{
		$cachable = true;

		// Set the default view name and format from the Request.
		$vName = $this->input->get('view', 'categories');
		$this->input->set('view', $vName);

		$user = JFactory::getUser();

		if ($user->get('id') || ($this->input->getMethod() === 'POST' && $vName === 'category'))
		{
			$cachable = false;
		}

		$safeurlparams = array('id' => 'INT', 'limit' => 'UINT', 'limitstart' => 'UINT',
								'filter_order' => 'CMD', 'filter_order_Dir' => 'CMD', 'lang' => 'CMD');

		parent::display($cachable, $safeurlparams);
	}
}
com_newsfeeds/newsfeeds.php000060400000001063152453734460012072 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

JLoader::register('NewsfeedsHelperRoute', JPATH_COMPONENT . '/helpers/route.php');
JTable::addIncludePath(JPATH_COMPONENT_ADMINISTRATOR . '/tables');

$controller = JControllerLegacy::getInstance('Newsfeeds');
$controller->execute(JFactory::getApplication()->input->get('task'));
$controller->redirect();
com_ajax/ajax.php000060400000014545152453734460010003 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

/*
 * References
 *  Support plugins in your component
 * - https://docs.joomla.org/Special:MyLanguage/Supporting_plugins_in_your_component
 *
 * Best way for JSON output
 * - https://groups.google.com/d/msg/joomla-dev-cms/WsC0nA9Fixo/Ur-gPqpqh-EJ
 */

/** @var \Joomla\CMS\Application\CMSApplication $app */
$app = JFactory::getApplication();
$app->allowCache(false);

// Prevent the api url from being indexed
$app->setHeader('X-Robots-Tag', 'noindex, nofollow');

// JInput object
$input = $app->input;

// Requested format passed via URL
$format = strtolower($input->getWord('format'));

// Initialize default response and module name
$results = null;
$parts   = null;

// Check for valid format
if (!$format)
{
	$results = new InvalidArgumentException(JText::_('COM_AJAX_SPECIFY_FORMAT'), 404);
}
/*
 * Module support.
 *
 * modFooHelper::getAjax() is called where 'foo' is the value
 * of the 'module' variable passed via the URL
 * (i.e. index.php?option=com_ajax&module=foo).
 *
 */
elseif ($input->get('module'))
{
	$module   = $input->get('module');
	$table    = JTable::getInstance('extension');
	$moduleId = $table->find(array('type' => 'module', 'element' => 'mod_' . $module));

	if ($moduleId && $table->load($moduleId) && $table->enabled)
	{
		$helperFile = JPATH_BASE . '/modules/mod_' . $module . '/helper.php';

		if (strpos($module, '_'))
		{
			$parts = explode('_', $module);
		}
		elseif (strpos($module, '-'))
		{
			$parts = explode('-', $module);
		}

		if ($parts)
		{
			$class = 'Mod';

			foreach ($parts as $part)
			{
				$class .= ucfirst($part);
			}

			$class .= 'Helper';
		}
		else
		{
			$class = 'Mod' . ucfirst($module) . 'Helper';
		}

		$method = $input->get('method') ?: 'get';

		if (is_file($helperFile))
		{
			JLoader::register($class, $helperFile);

			if (method_exists($class, $method . 'Ajax'))
			{
				// Load language file for module
				$basePath = JPATH_BASE;
				$lang     = JFactory::getLanguage();
				$lang->load('mod_' . $module, $basePath, null, false, true)
				||  $lang->load('mod_' . $module, $basePath . '/modules/mod_' . $module, null, false, true);

				try
				{
					$results = call_user_func($class . '::' . $method . 'Ajax');
				}
				catch (Exception $e)
				{
					$results = $e;
				}
			}
			// Method does not exist
			else
			{
				$results = new LogicException(JText::sprintf('COM_AJAX_METHOD_NOT_EXISTS', $method . 'Ajax'), 404);
			}
		}
		// The helper file does not exist
		else
		{
			$results = new RuntimeException(JText::sprintf('COM_AJAX_FILE_NOT_EXISTS', 'mod_' . $module . '/helper.php'), 404);
		}
	}
	// Module is not published, you do not have access to it, or it is not assigned to the current menu item
	else
	{
		$results = new LogicException(JText::sprintf('COM_AJAX_MODULE_NOT_ACCESSIBLE', 'mod_' . $module), 404);
	}
}
/*
 * Plugin support by default is based on the "Ajax" plugin group.
 * An optional 'group' variable can be passed via the URL.
 *
 * The plugin event triggered is onAjaxFoo, where 'foo' is
 * the value of the 'plugin' variable passed via the URL
 * (i.e. index.php?option=com_ajax&plugin=foo)
 *
 */
elseif ($input->get('plugin'))
{
	$group      = $input->get('group', 'ajax');
	JPluginHelper::importPlugin($group);
	$plugin     = ucfirst($input->get('plugin'));
	$dispatcher = JEventDispatcher::getInstance();

	try
	{
		$results = $dispatcher->trigger('onAjax' . $plugin);
	}
	catch (Exception $e)
	{
		$results = $e;
	}
}
/*
 * Template support.
 *
 * tplFooHelper::getAjax() is called where 'foo' is the value
 * of the 'template' variable passed via the URL
 * (i.e. index.php?option=com_ajax&template=foo).
 *
 */
elseif ($input->get('template'))
{
	$template   = $input->get('template');
	$table      = JTable::getInstance('extension');
	$templateId = $table->find(array('type' => 'template', 'element' => $template));

	if ($templateId && $table->load($templateId) && $table->enabled)
	{
		$basePath   = ($table->client_id) ? JPATH_ADMINISTRATOR : JPATH_SITE;
		$helperFile = $basePath . '/templates/' . $template . '/helper.php';

		if (strpos($template, '_'))
		{
			$parts = explode('_', $template);
		}
		elseif (strpos($template, '-'))
		{
			$parts = explode('-', $template);
		}

		if ($parts)
		{
			$class = 'Tpl';

			foreach ($parts as $part)
			{
				$class .= ucfirst($part);
			}

			$class .= 'Helper';
		}
		else
		{
			$class = 'Tpl' . ucfirst($template) . 'Helper';
		}

		$method = $input->get('method') ?: 'get';

		if (is_file($helperFile))
		{
			JLoader::register($class, $helperFile);

			if (method_exists($class, $method . 'Ajax'))
			{
				// Load language file for template
				$lang = JFactory::getLanguage();
				$lang->load('tpl_' . $template, $basePath, null, false, true)
				||  $lang->load('tpl_' . $template, $basePath . '/templates/' . $template, null, false, true);

				try
				{
					$results = call_user_func($class . '::' . $method . 'Ajax');
				}
				catch (Exception $e)
				{
					$results = $e;
				}
			}
			// Method does not exist
			else
			{
				$results = new LogicException(JText::sprintf('COM_AJAX_METHOD_NOT_EXISTS', $method . 'Ajax'), 404);
			}
		}
		// The helper file does not exist
		else
		{
			$results = new RuntimeException(JText::sprintf('COM_AJAX_FILE_NOT_EXISTS', 'tpl_' . $template . '/helper.php'), 404);
		}
	}
	// Template is not assigned to the current menu item
	else
	{
		$results = new LogicException(JText::sprintf('COM_AJAX_TEMPLATE_NOT_ACCESSIBLE', 'tpl_' . $template), 404);
	}
}

// Return the results in the desired format
switch ($format)
{
	// JSONinzed
	case 'json' :

		echo new JResponseJson($results, null, false, $input->get('ignoreMessages', true, 'bool'));

		break;

	// Handle as raw format
	default :
		// Output exception
		if ($results instanceof Exception)
		{
			// Log an error
			JLog::add($results->getMessage(), JLog::ERROR);

			// Set status header code
			$app->setHeader('status', $results->getCode(), true);

			// Echo exception type and message
			$out = get_class($results) . ': ' . $results->getMessage();
		}
		// Output string/ null
		elseif (is_scalar($results))
		{
			$out = (string) $results;
		}
		// Output array/ object
		else
		{
			$out = implode((array) $results);
		}

		echo $out;

		break;
}
com_finder/controller.php000060400000003032152453734460011554 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;

JLoader::register('FinderHelperLanguage', JPATH_ADMINISTRATOR . '/components/com_finder/helpers/language.php');

/**
 * Finder Component Controller.
 *
 * @since  2.5
 */
class FinderController extends JControllerLegacy
{
	/**
	 * Method to display a view.
	 *
	 * @param   boolean  $cachable   If true, the view output will be cached. [optional]
	 * @param   array    $urlparams  An array of safe URL parameters and their variable types,
	 *                               for valid values see {@link JFilterInput::clean()}. [optional]
	 *
	 * @return  JControllerLegacy  This object is to support chaining.
	 *
	 * @since   2.5
	 */
	public function display($cachable = false, $urlparams = array())
	{
		$input = JFactory::getApplication()->input;
		$cachable = true;

		// Load plugin language files.
		FinderHelperLanguage::loadPluginLanguage();

		// Set the default view name and format from the Request.
		$viewName = $input->get('view', 'search', 'word');
		$input->set('view', $viewName);

		// Don't cache view for search queries
		if ($input->get('q', null, 'string') || $input->get('f', null, 'int') || $input->get('t', null, 'array'))
		{
			$cachable = false;
		}

		$safeurlparams = array(
			'f'    => 'INT',
			'lang' => 'CMD'
		);

		return parent::display($cachable, $safeurlparams);
	}
}
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.php000060400000000747152453734460010652 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;

JLoader::register('FinderHelperRoute', JPATH_COMPONENT . '/helpers/route.php');

$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.php000060400000000757152453734460010437 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('UsersHelperRoute', JPATH_COMPONENT . '/helpers/route.php');

$controller = JControllerLegacy::getInstance('Users');
$controller->execute(JFactory::getApplication()->input->get('task', 'display'));
$controller->redirect();
com_users/controller.php000060400000007067152453734460011462 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;

/**
 * Base controller class for Users.
 *
 * @since  1.5
 */
class UsersController 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)
	{
		// Get the document object.
		$document = JFactory::getDocument();

		// Set the default view name and format from the Request.
		$vName   = $this->input->getCmd('view', 'login');
		$vFormat = $document->getType();
		$lName   = $this->input->getCmd('layout', 'default');

		if ($view = $this->getView($vName, $vFormat))
		{
			// Do any specific processing by view.
			switch ($vName)
			{
				case 'registration':
					// If the user is already logged in, redirect to the profile page.
					$user = JFactory::getUser();

					if ($user->get('guest') != 1)
					{
						// Redirect to profile page.
						$this->setRedirect(JRoute::_('index.php?option=com_users&view=profile', false));

						return;
					}

					// Check if user registration is enabled
					if (JComponentHelper::getParams('com_users')->get('allowUserRegistration') == 0)
					{
						// Registration is disabled - Redirect to login page.
						$this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));

						return;
					}

					// The user is a guest, load the registration model and show the registration page.
					$model = $this->getModel('Registration');
					break;

				// Handle view specific models.
				case 'profile':

					// If the user is a guest, redirect to the login page.
					$user = JFactory::getUser();

					if ($user->get('guest') == 1)
					{
						// Redirect to login page.
						$this->setRedirect(JRoute::_('index.php?option=com_users&view=login', false));

						return;
					}

					$model = $this->getModel($vName);
					break;

				// Handle the default views.
				case 'login':
					$model = $this->getModel($vName);
					break;

				case 'reset':
					// If the user is already logged in, redirect to the profile page.
					$user = JFactory::getUser();

					if ($user->get('guest') != 1)
					{
						// Redirect to profile page.
						$this->setRedirect(JRoute::_('index.php?option=com_users&view=profile', false));

						return;
					}

					$model = $this->getModel($vName);
					break;

				case 'remind':
					// If the user is already logged in, redirect to the profile page.
					$user = JFactory::getUser();

					if ($user->get('guest') != 1)
					{
						// Redirect to profile page.
						$this->setRedirect(JRoute::_('index.php?option=com_users&view=profile', false));

						return;
					}

					$model = $this->getModel($vName);
					break;

				default:
					$model = $this->getModel('Login');
					break;
			}

			// Make sure we don't send a referer
			if (in_array($vName, array('remind', 'reset')))
			{
				JFactory::getApplication()->setHeader('Referrer-Policy', 'no-referrer', true);
			}

			// 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();
		}
	}
}
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.php000060400000010607152453734460013040 0ustar00<?php
/**
 * @package     Joomla.Site
 * @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;

/**
 * Users Html Helper
 *
 * @since  1.6
 */
abstract class JHtmlUsers
{
	/**
	 * Get the sanitized value
	 *
	 * @param   mixed  $value  Value of the field
	 *
	 * @return  mixed  String/void
	 *
	 * @since   1.6
	 */
	public static function value($value)
	{
		if (is_string($value))
		{
			$value = trim($value);
		}

		if (empty($value))
		{
			return JText::_('COM_USERS_PROFILE_VALUE_NOT_FOUND');
		}

		elseif (!is_array($value))
		{
			return htmlspecialchars($value, ENT_COMPAT, 'UTF-8');
		}
	}

	/**
	 * Get the space symbol
	 *
	 * @param   mixed  $value  Value of the field
	 *
	 * @return  string
	 *
	 * @since   1.6
	 */
	public static function spacer($value)
	{
		return '';
	}

	/**
	 * Get the sanitized helpsite link
	 *
	 * @param   mixed  $value  Value of the field
	 *
	 * @return  mixed  String/void
	 *
	 * @since   1.6
	 */
	public static function helpsite($value)
	{
		if (empty($value))
		{
			return static::value($value);
		}

		$text = $value;

		if ($xml = simplexml_load_file(JPATH_ADMINISTRATOR . '/help/helpsites.xml'))
		{
			foreach ($xml->sites->site as $site)
			{
				if ((string) $site->attributes()->url == $value)
				{
					$text = (string) $site;
					break;
				}
			}
		}

		$value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8');

		if (strpos($value, 'http') === 0)
		{
			return '<a href="' . $value . '">' . $text . '</a>';
		}

		return '<a href="http://' . $value . '">' . $text . '</a>';
	}

	/**
	 * Get the sanitized template style
	 *
	 * @param   mixed  $value  Value of the field
	 *
	 * @return  mixed  String/void
	 *
	 * @since   1.6
	 */
	public static function templatestyle($value)
	{
		if (empty($value))
		{
			return static::value($value);
		}
		else
		{
			$db = JFactory::getDbo();
			$query = $db->getQuery(true)
				->select('title')
				->from('#__template_styles')
				->where('id = ' . $db->quote($value));
			$db->setQuery($query);
			$title = $db->loadResult();

			if ($title)
			{
				return htmlspecialchars($title, ENT_COMPAT, 'UTF-8');
			}
			else
			{
				return static::value('');
			}
		}
	}

	/**
	 * Get the sanitized language
	 *
	 * @param   mixed  $value  Value of the field
	 *
	 * @return  mixed  String/void
	 *
	 * @since   1.6
	 */
	public static function admin_language($value)
	{
		if (empty($value))
		{
			return static::value($value);
		}
		else
		{
			$file = JLanguageHelper::getLanguagePath(JPATH_ADMINISTRATOR, $value) . '/' . $value . '.xml';

			$result = null;

			if (is_file($file))
			{
				$result = JLanguageHelper::parseXMLLanguageFile($file);
			}

			if ($result)
			{
				return htmlspecialchars($result['name'], ENT_COMPAT, 'UTF-8');
			}
			else
			{
				return static::value('');
			}
		}
	}

	/**
	 * Get the sanitized language
	 *
	 * @param   mixed  $value  Value of the field
	 *
	 * @return  mixed  String/void
	 *
	 * @since   1.6
	 */
	public static function language($value)
	{
		if (empty($value))
		{
			return static::value($value);
		}
		else
		{
			$file = JLanguageHelper::getLanguagePath(JPATH_SITE, $value) . '/' . $value . '.xml';

			$result = null;

			if (is_file($file))
			{
				$result = JLanguageHelper::parseXMLLanguageFile($file);
			}

			if ($result)
			{
				return htmlspecialchars($result['name'], ENT_COMPAT, 'UTF-8');
			}
			else
			{
				return static::value('');
			}
		}
	}

	/**
	 * Get the sanitized editor name
	 *
	 * @param   mixed  $value  Value of the field
	 *
	 * @return  mixed  String/void
	 *
	 * @since   1.6
	 */
	public static function editor($value)
	{
		if (empty($value))
		{
			return static::value($value);
		}
		else
		{
			$db = JFactory::getDbo();
			$lang = JFactory::getLanguage();
			$query = $db->getQuery(true)
				->select('name')
				->from('#__extensions')
				->where('element = ' . $db->quote($value))
				->where('folder = ' . $db->quote('editors'));
			$db->setQuery($query);
			$title = $db->loadResult();

			if ($title)
			{
				$lang->load("plg_editors_$value.sys", JPATH_ADMINISTRATOR, null, false, true)
					|| $lang->load("plg_editors_$value.sys", JPATH_PLUGINS . '/editors/' . $value, null, false, true);
				$lang->load($title . '.sys');

				return JText::_($title);
			}
			else
			{
				return static::value('');
			}
		}
	}
}
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.php000060400000020634152453734460012616 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 UsersControllerUser extends UsersController
{
	/**
	 * Method to log in a user.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function login()
	{
		$this->checkToken('post');

		$app   = JFactory::getApplication();
		$input = $app->input->getInputForRequestMethod();

		// Populate the data array:
		$data = array();

		$data['return']    = base64_decode($input->get('return', '', 'BASE64'));
		$data['username']  = $input->get('username', '', 'USERNAME');
		$data['password']  = $input->get('password', '', 'RAW');
		$data['secretkey'] = $input->get('secretkey', '', 'RAW');

		// Check for a simple menu item id
		if (is_numeric($data['return']))
		{
			if (JLanguageMultilang::isEnabled())
			{
				$db = JFactory::getDbo();
				$query = $db->getQuery(true)
					->select('language')
					->from($db->quoteName('#__menu'))
					->where('client_id = 0')
					->where('id =' . $data['return']);

				$db->setQuery($query);

				try
				{
					$language = $db->loadResult();
				}
				catch (RuntimeException $e)
				{
					return;
				}

				if ($language !== '*')
				{
					$lang = '&lang=' . $language;
				}
				else
				{
					$lang = '';
				}
			}
			else
			{
				$lang = '';
			}

			$data['return'] = 'index.php?Itemid=' . $data['return'] . $lang;
		}
		else
		{
			// Don't redirect to an external URL.
			if (!JUri::isInternal($data['return']))
			{
				$data['return'] = '';
			}
		}

		// Set the return URL if empty.
		if (empty($data['return']))
		{
			$data['return'] = 'index.php?option=com_users&view=profile';
		}

		// Set the return URL in the user state to allow modification by plugins
		$app->setUserState('users.login.form.return', $data['return']);

		// Get the log in options.
		$options = array();
		$options['remember'] = $this->input->getBool('remember', false);
		$options['return']   = $data['return'];

		// Get the log in credentials.
		$credentials = array();
		$credentials['username']  = $data['username'];
		$credentials['password']  = $data['password'];
		$credentials['secretkey'] = $data['secretkey'];

		// Perform the log in.
		if (true !== $app->login($credentials, $options))
		{
			// Login failed !
			// Clear user name, password and secret key before sending the login form back to the user.
			$data['remember'] = (int) $options['remember'];
			$data['username'] = '';
			$data['password'] = '';
			$data['secretkey'] = '';
			$app->setUserState('users.login.form.data', $data);
			$app->redirect(JRoute::_('index.php?option=com_users&view=login', false));
		}

		// Success
		if ($options['remember'] == true)
		{
			$app->setUserState('rememberLogin', true);
		}

		$app->setUserState('users.login.form.data', array());
		$app->redirect(JRoute::_($app->getUserState('users.login.form.return'), false));
	}

	/**
	 * Method to log out a user.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function logout()
	{
		$this->checkToken('request');

		$app = JFactory::getApplication();

		// Prepare the logout options.
		$options = array(
			'clientid' => $app->get('shared_session', '0') ? null : 0,
		);

		// Perform the log out.
		$error = $app->logout(null, $options);
		$input = $app->input->getInputForRequestMethod();

		// Check if the log out succeeded.
		if ($error instanceof Exception)
		{
			$app->redirect(JRoute::_('index.php?option=com_users&view=login', false));
		}

		// Get the return URL from the request and validate that it is internal.
		$return = $input->get('return', '', 'BASE64');
		$return = base64_decode($return);

		// Check for a simple menu item id
		if (is_numeric($return))
		{
			if (JLanguageMultilang::isEnabled())
			{
				$db = JFactory::getDbo();
				$query = $db->getQuery(true)
					->select('language')
					->from($db->quoteName('#__menu'))
					->where('client_id = 0')
					->where('id =' . $return);

				$db->setQuery($query);

				try
				{
					$language = $db->loadResult();
				}
				catch (RuntimeException $e)
				{
					return;
				}

				if ($language !== '*')
				{
					$lang = '&lang=' . $language;
				}
				else
				{
					$lang = '';
				}
			}
			else
			{
				$lang = '';
			}

			$return = 'index.php?Itemid=' . $return . $lang;
		}
		else
		{
			// Don't redirect to an external URL.
			if (!JUri::isInternal($return))
			{
				$return = '';
			}
		}

		// In case redirect url is not set, redirect user to homepage
		if (empty($return))
		{
			$return = JUri::root();
		}

		// Redirect the user.
		$app->redirect(JRoute::_($return, false));
	}

	/**
	 * Method to logout directly and redirect to page.
	 *
	 * @return  void
	 *
	 * @since   3.5
	 */
	public function menulogout()
	{
		// Get the ItemID of the page to redirect after logout
		$app    = JFactory::getApplication();
		$active = $app->getMenu()->getActive();
		$itemid = $active ? $active->getParams()->get('logout') : 0;
		
		// Get the language of the page when multilang is on
		if (JLanguageMultilang::isEnabled())
		{
			if ($itemid)
			{
				$db = JFactory::getDbo();
				$query = $db->getQuery(true)
					->select('language')
					->from($db->quoteName('#__menu'))
					->where('client_id = 0')
					->where('id =' . $itemid);

				$db->setQuery($query);

				try
				{
					$language = $db->loadResult();
				}
				catch (RuntimeException $e)
				{
					return;
				}

				if ($language !== '*')
				{
					$lang = '&lang=' . $language;
				}
				else
				{
					$lang = '';
				}

				// URL to redirect after logout
				$url = 'index.php?Itemid=' . $itemid . $lang;
			}
			else
			{
				// Logout is set to default. Get the home page ItemID
				$lang_code = $app->input->cookie->getString(JApplicationHelper::getHash('language'));
				$item      = $app->getMenu()->getDefault($lang_code);
				$itemid    = $item->id;

				// Redirect to Home page after logout
				$url = 'index.php?Itemid=' . $itemid;
			}
		}
		else
		{
			// URL to redirect after logout, default page if no ItemID is set
			$url = $itemid ? 'index.php?Itemid=' . $itemid : JUri::root();
		}

		// Logout and redirect
		$this->setRedirect('index.php?option=com_users&task=user.logout&' . JSession::getFormToken() . '=1&return=' . base64_encode($url));
	}

	/**
	 * Method to request a username reminder.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function remind()
	{
		// Check the request token.
		$this->checkToken('post');

		$app   = JFactory::getApplication();
		$model = $this->getModel('User', 'UsersModel');
		$data  = $this->input->post->get('jform', array(), 'array');

		// Submit the username remind request.
		$return = $model->processRemindRequest($data);

		// Check for a hard error.
		if ($return instanceof Exception)
		{
			// Get the error message to display.
			$message = $app->get('error_reporting')
				? $return->getMessage()
				: JText::_('COM_USERS_REMIND_REQUEST_ERROR');

			// Get the route to the next page.
			$itemid = UsersHelperRoute::getRemindRoute();
			$itemid = $itemid !== null ? '&Itemid=' . $itemid : '';
			$route  = 'index.php?option=com_users&view=remind' . $itemid;

			// Go back to the complete form.
			$this->setRedirect(JRoute::_($route, false), $message, 'error');

			return false;
		}

		if ($return === false)
		{
			// Complete failed.
			// Get the route to the next page.
			$itemid = UsersHelperRoute::getRemindRoute();
			$itemid = $itemid !== null ? '&Itemid=' . $itemid : '';
			$route  = 'index.php?option=com_users&view=remind' . $itemid;

			// Go back to the complete form.
			$message = JText::sprintf('COM_USERS_REMIND_REQUEST_FAILED', $model->getError());
			$this->setRedirect(JRoute::_($route, false), $message, 'notice');

			return false;
		}

		// Complete succeeded.
		// Get the route to the next page.
		$itemid = UsersHelperRoute::getLoginRoute();
		$itemid = $itemid !== null ? '&Itemid=' . $itemid : '';
		$route	= 'index.php?option=com_users&view=login' . $itemid;

		// Proceed to the login form.
		$message = JText::_('COM_USERS_REMIND_REQUEST_SUCCESS');
		$this->setRedirect(JRoute::_($route, false), $message);

		return true;
	}

	/**
	 * Method to resend a user.
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	public function resend()
	{
		// Check for request forgeries
		// $this->checkToken('post');
	}
}
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.php000060400000001245152453734460010640 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 classes
JLoader::registerPrefix('Config', JPATH_COMPONENT);

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

// Tell the browser not to cache this page.
$app->setHeader('Expires', 'Mon, 26 Jul 1997 05:00:00 GMT', true);

$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>