uawdijnntqw1x1x1
IP : 216.73.216.231
Hostname : 213-108-241-110.cprapid.com
Kernel : Linux 213-108-241-110.cprapid.com 5.14.0-570.25.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jul 9 04:57:09 EDT 2025 x86_64
Disable Function : None :)
OS : Linux
PATH:
/
home
/
digilove
/
public_html
/
modules
/
mod_marketplacemenus
/
..
/
..
/
41423
/
fof30.tar
/
/
Autoloader/Autoloader.php000064400000014014152325653660011470 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Autoloader; // Do not put the JEXEC or die check on this file (necessary omission for testing) /** * A PSR-4 class autoloader. This is a modified version of Composer's ClassLoader class * * @codeCoverageIgnore */ class Autoloader { /** @var array Lengths of PSR-4 prefixes */ private $prefixLengths = array(); /** @var array Prefix to directory map */ private $prefixDirs = array(); /** @var array Fall-back directories */ private $fallbackDirs = array(); /** @var Autoloader The static instance of this autoloader */ private static $instance; /** * @return Autoloader */ public static function getInstance() { if (!is_object(self::$instance)) { self::$instance = new Autoloader(); } return self::$instance; } /** * Returns the prefix to directory map * * @return array */ public function getPrefixes() { return $this->prefixDirs; } /** * Returns the list of fall=back directories * * @return array */ public function getFallbackDirs() { return $this->fallbackDirs; } /** * Registers a set of PSR-4 directories for a given namespace, either * appending or prefixing to the ones previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-0 base directories * @param boolean $prepend Whether to prefix the directories * * @return $this for chaining * * @throws \InvalidArgumentException When the prefix is invalid */ public function addMap($prefix, $paths, $prepend = false) { if ($prefix) { $prefix = ltrim($prefix, '\\'); } if (!$prefix) { // Register directories for the root namespace. if ($prepend) { $this->fallbackDirs = array_merge( (array)$paths, $this->fallbackDirs ); $this->fallbackDirs = array_unique($this->fallbackDirs); } else { $this->fallbackDirs = array_merge( $this->fallbackDirs, (array)$paths ); $this->fallbackDirs = array_unique($this->fallbackDirs); } } elseif (!isset($this->prefixDirs[$prefix])) { // Register directories for a new namespace. $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) { throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengths[$prefix[0]][$prefix] = $length; $this->prefixDirs[$prefix] = (array)$paths; } elseif ($prepend) { // Prepend directories for an already registered namespace. $this->prefixDirs[$prefix] = array_merge( (array)$paths, $this->prefixDirs[$prefix] ); $this->prefixDirs[$prefix] = array_unique($this->prefixDirs[$prefix]); } else { // Append directories for an already registered namespace. $this->prefixDirs[$prefix] = array_merge( $this->prefixDirs[$prefix], (array)$paths ); $this->prefixDirs[$prefix] = array_unique($this->prefixDirs[$prefix]); } return $this; } /** * Does the autoloader have a map for the specified prefix? * * @param string $prefix * * @return bool */ public function hasMap($prefix) { return isset($this->prefixDirs[$prefix]); } /** * Registers a set of PSR-4 directories for a given namespace, * replacing any others previously set for this namespace. * * @param string $prefix The prefix/namespace, with trailing '\\' * @param array|string $paths The PSR-4 base directories * * @return void * * @throws \InvalidArgumentException When the prefix is invalid */ public function setMap($prefix, $paths) { if ($prefix) { $prefix = ltrim($prefix, '\\'); } if (!$prefix) { $this->fallbackDirs = (array)$paths; } else { $length = strlen($prefix); if ('\\' !== $prefix[$length - 1]) { throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator."); } $this->prefixLengths[$prefix[0]][$prefix] = $length; $this->prefixDirs[$prefix] = (array)$paths; } } /** * Registers this instance as an autoloader. * * @param boolean $prepend Whether to prepend the autoloader or not * * @return void */ public function register($prepend = false) { spl_autoload_register(array($this, 'loadClass'), true, $prepend); } /** * Unregisters this instance as an autoloader. * * @return void */ public function unregister() { spl_autoload_unregister(array($this, 'loadClass')); } /** * Loads the given class or interface. * * @param string $class The name of the class * * @return boolean|null True if loaded, null otherwise */ public function loadClass($class) { if ($file = $this->findFile($class)) { include $file; return true; } } /** * Finds the path to the file where the class is defined. * * @param string $class The name of the class * * @return string|false The path if found, false otherwise */ public function findFile($class) { // work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731 if ('\\' == $class[0]) { $class = substr($class, 1); } // PSR-4 lookup $logicalPath = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php'; $first = $class[0]; if (isset($this->prefixLengths[$first])) { foreach ($this->prefixLengths[$first] as $prefix => $length) { if (0 === strpos($class, $prefix)) { foreach ($this->prefixDirs[$prefix] as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPath, $length))) { return $file; } } } } } // PSR-4 fallback dirs foreach ($this->fallbackDirs as $dir) { if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPath)) { return $file; } } } } // Register the current namespace with the autoloader Autoloader::getInstance()->addMap('FOF30\\', array(realpath(__DIR__ . '/..'))); Autoloader::getInstance()->register(); Configuration/Domain/Authentication.php000064400000003274152325653670014276 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Configuration\Domain; use SimpleXMLElement; defined('_JEXEC') or die; /** * Configuration parser for the authentication-specific settings * * @since 2.1 */ class Authentication implements DomainInterface { /** * Parse the XML data, adding them to the $ret array * * @param SimpleXMLElement $xml The XML data of the component's configuration area * @param array &$ret The parsed data, in the form of a hash array * * @return void */ public function parseDomain(SimpleXMLElement $xml, array &$ret) { // Initialise $ret['authentication'] = array(); // Parse the dispatcher configuration $authenticationData = $xml->authentication; // Sanity check if (empty($authenticationData)) { return; } $options = $xml->xpath('authentication/option'); if (!empty($options)) { foreach ($options as $option) { $key = (string) $option['name']; $ret['authentication'][$key] = (string) $option; } } } /** * Return a configuration variable * * @param string &$configuration Configuration variables (hashed array) * @param string $var The variable we want to fetch * @param mixed $default Default value * * @return mixed The variable's value */ public function get(&$configuration, $var, $default) { if ($var == '*') { return $configuration['authentication']; } if (isset($configuration['authentication'][$var])) { return $configuration['authentication'][$var]; } else { return $default; } } } Configuration/Domain/Container.php000064400000003205152325653670013233 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Configuration\Domain; use SimpleXMLElement; defined('_JEXEC') or die; /** * Configuration parser for the Container-specific settings * * @since 2.1 */ class Container implements DomainInterface { /** * Parse the XML data, adding them to the $ret array * * @param SimpleXMLElement $xml The XML data of the component's configuration area * @param array &$ret The parsed data, in the form of a hash array * * @return void */ public function parseDomain(SimpleXMLElement $xml, array &$ret) { // Initialise $ret['container'] = array(); // Parse the dispatcher configuration $containerData = $xml->container; // Sanity check if (empty($containerData)) { return; } $options = $xml->xpath('container/option'); if (!empty($options)) { foreach ($options as $option) { $key = (string) $option['name']; $ret['container'][$key] = (string) $option; } } } /** * Return a configuration variable * * @param string &$configuration Configuration variables (hashed array) * @param string $var The variable we want to fetch * @param mixed $default Default value * * @return mixed The variable's value */ public function get(&$configuration, $var, $default) { if ($var == '*') { return $configuration['container']; } if (isset($configuration['container'][$var])) { return $configuration['container'][$var]; } else { return $default; } } } Configuration/Domain/Dispatcher.php000064400000003220152325653670013374 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Configuration\Domain; use SimpleXMLElement; defined('_JEXEC') or die; /** * Configuration parser for the dispatcher-specific settings * * @since 2.1 */ class Dispatcher implements DomainInterface { /** * Parse the XML data, adding them to the $ret array * * @param SimpleXMLElement $xml The XML data of the component's configuration area * @param array &$ret The parsed data, in the form of a hash array * * @return void */ public function parseDomain(SimpleXMLElement $xml, array &$ret) { // Initialise $ret['dispatcher'] = array(); // Parse the dispatcher configuration $dispatcherData = $xml->dispatcher; // Sanity check if (empty($dispatcherData)) { return; } $options = $xml->xpath('dispatcher/option'); if (!empty($options)) { foreach ($options as $option) { $key = (string) $option['name']; $ret['dispatcher'][$key] = (string) $option; } } } /** * Return a configuration variable * * @param string &$configuration Configuration variables (hashed array) * @param string $var The variable we want to fetch * @param mixed $default Default value * * @return mixed The variable's value */ public function get(&$configuration, $var, $default) { if ($var == '*') { return $configuration['dispatcher']; } if (isset($configuration['dispatcher'][$var])) { return $configuration['dispatcher'][$var]; } else { return $default; } } } Configuration/Domain/DomainInterface.php000064400000002240152325653670014337 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Configuration\Domain; use SimpleXMLElement; defined('_JEXEC') or die; /** * The Interface of a FOF configuration domain class. The methods are used to parse and * provision sensible information to consumers. The Configuration class acts as an * adapter to the domain classes. * * @since 2.1 */ interface DomainInterface { /** * Parse the XML data, adding them to the $ret array * * @param SimpleXMLElement $xml The XML data of the component's configuration area * @param array &$ret The parsed data, in the form of a hash array * * @return void */ public function parseDomain(SimpleXMLElement $xml, array &$ret); /** * Return a configuration variable * * @param string &$configuration Configuration variables (hashed array) * @param string $var The variable we want to fetch * @param mixed $default Default value * * @return mixed The variable's value */ public function get(&$configuration, $var, $default); } Configuration/Domain/Models.php000064400000022733152325653670012543 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Configuration\Domain; use SimpleXMLElement; defined('_JEXEC') or die; /** * Configuration parser for the models-specific settings * * @since 2.1 */ class Models implements DomainInterface { /** * Parse the XML data, adding them to the $ret array * * @param SimpleXMLElement $xml The XML data of the component's configuration area * @param array &$ret The parsed data, in the form of a hash array * * @return void */ public function parseDomain(SimpleXMLElement $xml, array &$ret) { // Initialise $ret['models'] = array(); // Parse model configuration $modelsData = $xml->xpath('model'); // Sanity check if (empty($modelsData)) { return; } foreach ($modelsData as $aModel) { $key = (string) $aModel['name']; $ret['models'][ $key ]['behaviors'] = array(); $ret['models'][ $key ]['behaviorsMerge'] = false; $ret['models'][ $key ]['tablealias'] = $aModel->xpath('tablealias'); $ret['models'][ $key ]['fields'] = array(); $ret['models'][ $key ]['relations'] = array(); $ret['models'][ $key ]['config'] = array(); // Parse configuration $optionData = $aModel->xpath('config/option'); if (!empty($optionData)) { foreach ($optionData as $option) { $k = (string) $option['name']; $ret['models'][ $key ]['config'][ $k ] = (string) $option; } } // Parse field aliases $fieldData = $aModel->xpath('field'); if (!empty($fieldData)) { foreach ($fieldData as $field) { $k = (string) $field['name']; $ret['models'][ $key ]['fields'][ $k ] = (string) $field; } } // Parse behaviours $behaviorsData = (string) $aModel->behaviors; $behaviorsMerge = (string) $aModel->behaviors['merge']; if (!empty($behaviorsMerge)) { $behaviorsMerge = trim($behaviorsMerge); $behaviorsMerge = strtoupper($behaviorsMerge); if (in_array($behaviorsMerge, array('1', 'YES', 'ON', 'TRUE'))) { $ret['models'][ $key ]['behaviorsMerge'] = true; } } if (!empty($behaviorsData)) { $behaviorsData = explode(',', $behaviorsData); foreach ($behaviorsData as $behavior) { $behavior = trim($behavior); if (empty($behavior)) { continue; } $ret['models'][ $key ]['behaviors'][] = $behavior; } } // Parse relations $relationsData = $aModel->xpath('relation'); if (!empty($relationsData)) { foreach ($relationsData as $relationData) { $type = (string) $relationData['type']; $itemName = (string) $relationData['name']; if (empty($type) || empty($itemName)) { continue; } $modelClass = (string) $relationData['foreignModelClass']; $localKey = (string) $relationData['localKey']; $foreignKey = (string) $relationData['foreignKey']; $pivotTable = (string) $relationData['pivotTable']; $ourPivotKey = (string) $relationData['pivotLocalKey']; $theirPivotKey = (string) $relationData['pivotForeignKey']; $relation = array( 'type' => $type, 'itemName' => $itemName, 'foreignModelClass' => empty($modelClass) ? null : $modelClass, 'localKey' => empty($localKey) ? null : $localKey, 'foreignKey' => empty($foreignKey) ? null : $foreignKey, ); if (!empty($ourPivotKey) || !empty($theirPivotKey) || !empty($pivotTable)) { $relation['pivotLocalKey'] = empty($ourPivotKey) ? null : $ourPivotKey; $relation['pivotForeignKey'] = empty($theirPivotKey) ? null : $theirPivotKey; $relation['pivotTable'] = empty($pivotTable) ? null : $pivotTable; } $ret['models'][ $key ]['relations'][] = $relation; } } } } /** * Return a configuration variable * * @param string &$configuration Configuration variables (hashed array) * @param string $var The variable we want to fetch * @param mixed $default Default value * * @return mixed The variable's value */ public function get(&$configuration, $var, $default) { $parts = explode('.', $var); $view = $parts[0]; $method = 'get' . ucfirst($parts[1]); if (!method_exists($this, $method)) { return $default; } array_shift($parts); array_shift($parts); $ret = $this->$method($view, $configuration, $parts, $default); return $ret; } /** * Internal method to return the magic field mapping * * @param string $model The model for which we will be fetching a field map * @param array &$configuration The configuration parameters hash array * @param array $params Extra options * @param string $default Default magic field mapping; empty if not defined * * @return array Field map */ protected function getField($model, &$configuration, $params, $default = '') { $fieldmap = array(); if (isset($configuration['models']['*']) && isset($configuration['models']['*']['fields'])) { $fieldmap = $configuration['models']['*']['fields']; } if (isset($configuration['models'][ $model ]) && isset($configuration['models'][ $model ]['fields'])) { $fieldmap = array_merge($fieldmap, $configuration['models'][ $model ]['fields']); } $map = $default; if (empty($params[0]) || ($params[0] == '*')) { $map = $fieldmap; } elseif (isset($fieldmap[ $params[0] ])) { $map = $fieldmap[ $params[0] ]; } return $map; } /** * Internal method to get model alias * * @param string $model The model for which we will be fetching table alias * @param array &$configuration The configuration parameters hash array * @param array $params Ignored * @param string $default Default table alias * * @return string Table alias */ protected function getTablealias($model, &$configuration, $params, $default = '') { $tableMap = array(); if (isset($configuration['models']['*']['tablealias'])) { $tableMap = $configuration['models']['*']['tablealias']; } if (isset($configuration['models'][ $model ]['tablealias'])) { $tableMap = array_merge($tableMap, $configuration['models'][ $model ]['tablealias']); } if (empty($tableMap)) { return null; } return $tableMap[0]; } /** * Internal method to get model behaviours * * @param string $model The model for which we will be fetching behaviours * @param array &$configuration The configuration parameters hash array * @param array $params Unused * @param string $default Default behaviour * * @return string Model behaviours */ protected function getBehaviors($model, &$configuration, $params, $default = '') { $behaviors = $default; if (isset($configuration['models']['*']) && isset($configuration['models']['*']['behaviors']) ) { $behaviors = $configuration['models']['*']['behaviors']; } if (isset($configuration['models'][ $model ]) && isset($configuration['models'][ $model ]['behaviors']) ) { $merge = false; if (isset($configuration['models'][ $model ]) && isset($configuration['models'][ $model ]['behaviorsMerge']) ) { $merge = (bool) $configuration['models'][ $model ]['behaviorsMerge']; } if ($merge) { $behaviors = array_merge($behaviors, $configuration['models'][ $model ]['behaviors']); } else { $behaviors = $configuration['models'][ $model ]['behaviors']; } } return $behaviors; } /** * Internal method to get model relations * * @param string $model The model for which we will be fetching relations * @param array &$configuration The configuration parameters hash array * @param array $params Unused * @param string $default Default relations * * @return array Model relations */ protected function getRelations($model, &$configuration, $params, $default = '') { $relations = $default; if (isset($configuration['models']['*']) && isset($configuration['models']['*']['relations']) ) { $relations = $configuration['models']['*']['relations']; } if (isset($configuration['models'][ $model ]) && isset($configuration['models'][ $model ]['relations']) ) { $relations = $configuration['models'][ $model ]['relations']; } return $relations; } /** * Internal method to return the a configuration option for the Model. * * @param string $model The view for which we will be fetching a task map * @param array &$configuration The configuration parameters hash array * @param array $params Extra options; key 0 defines the option variable we want to fetch * @param mixed $default Default option; null if not defined * * @return string The setting for the requested option */ protected function getConfig($model, &$configuration, $params, $default = null) { $ret = $default; $config = array(); if (isset($configuration['models']['*']['config'])) { $config = $configuration['models']['*']['config']; } if (isset($configuration['models'][ $model ]['config'])) { $config = array_merge($config, $configuration['models'][ $model ]['config']); } if (empty($params) || empty($params[0])) { return $config; } if (isset($config[ $params[0] ])) { $ret = $config[ $params[0] ]; } return $ret; } } Configuration/Domain/Views.php000064400000020131152325653670012403 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Configuration\Domain; use SimpleXMLElement; defined('_JEXEC') or die; /** * Configuration parser for the view-specific settings * * @since 2.1 */ class Views implements DomainInterface { /** * Parse the XML data, adding them to the $ret array * * @param SimpleXMLElement $xml The XML data of the component's configuration area * @param array &$ret The parsed data, in the form of a hash array * * @return void */ public function parseDomain(SimpleXMLElement $xml, array &$ret) { // Initialise $ret['views'] = array(); // Parse view configuration $viewData = $xml->xpath('view'); // Sanity check if (empty($viewData)) { return; } foreach ($viewData as $aView) { $key = (string) $aView['name']; // Parse ACL options $ret['views'][$key]['acl'] = array(); $aclData = $aView->xpath('acl/task'); if (!empty($aclData)) { foreach ($aclData as $acl) { $k = (string) $acl['name']; $ret['views'][$key]['acl'][$k] = (string) $acl; } } // Parse taskmap $ret['views'][$key]['taskmap'] = array(); $taskmapData = $aView->xpath('taskmap/task'); if (!empty($taskmapData)) { foreach ($taskmapData as $map) { $k = (string) $map['name']; $ret['views'][$key]['taskmap'][$k] = (string) $map; } } // Parse controller configuration $ret['views'][$key]['config'] = array(); $optionData = $aView->xpath('config/option'); if (!empty($optionData)) { foreach ($optionData as $option) { $k = (string) $option['name']; $ret['views'][$key]['config'][$k] = (string) $option; } } // Parse the toolbar $ret['views'][$key]['toolbar'] = array(); $toolBars = $aView->xpath('toolbar'); if (!empty($toolBars)) { foreach ($toolBars as $toolBar) { $taskName = isset($toolBar['task']) ? (string) $toolBar['task'] : '*'; // If a toolbar title is specified, create a title element. if (isset($toolBar['title'])) { $ret['views'][$key]['toolbar'][$taskName]['title'] = array( 'value' => (string) $toolBar['title'] ); } // Parse the toolbar buttons data $toolbarData = $toolBar->xpath('button'); if (!empty($toolbarData)) { foreach ($toolbarData as $button) { $k = (string) $button['type']; $ret['views'][$key]['toolbar'][$taskName][$k] = current($button->attributes()); $ret['views'][$key]['toolbar'][$taskName][$k]['value'] = (string) $button; } } } } } } /** * Return a configuration variable * * @param string &$configuration Configuration variables (hashed array) * @param string $var The variable we want to fetch * @param mixed $default Default value * * @return mixed The variable's value */ public function get(&$configuration, $var, $default) { $parts = explode('.', $var); $view = $parts[0]; $method = 'get' . ucfirst($parts[1]); if (!method_exists($this, $method)) { return $default; } array_shift($parts); array_shift($parts); $ret = $this->$method($view, $configuration, $parts, $default); return $ret; } /** * Internal function to return the task map for a view * * @param string $view The view for which we will be fetching a task map * @param array &$configuration The configuration parameters hash array * @param array $params Extra options (not used) * @param array $default ßDefault task map; empty array if not provided * * @return array The task map as a hash array in the format task => method */ protected function getTaskmap($view, &$configuration, $params, $default = array()) { $taskmap = array(); if (isset($configuration['views']['*']) && isset($configuration['views']['*']['taskmap'])) { $taskmap = $configuration['views']['*']['taskmap']; } if (isset($configuration['views'][$view]) && isset($configuration['views'][$view]['taskmap'])) { $taskmap = array_merge($taskmap, $configuration['views'][$view]['taskmap']); } if (empty($taskmap)) { return $default; } return $taskmap; } /** * Internal method to return the ACL mapping (privilege required to access * a specific task) for the given view's tasks * * @param string $view The view for which we will be fetching a task map * @param array &$configuration The configuration parameters hash array * @param array $params Extra options; key 0 defines the task we want to fetch * @param string $default Default ACL option; empty (no ACL check) if not defined * * @return string The privilege required to access this view */ protected function getAcl($view, &$configuration, $params, $default = '') { $aclmap = array(); if (isset($configuration['views']['*']) && isset($configuration['views']['*']['acl'])) { $aclmap = $configuration['views']['*']['acl']; } if (isset($configuration['views'][$view]) && isset($configuration['views'][$view]['acl'])) { $aclmap = array_merge($aclmap, $configuration['views'][$view]['acl']); } $acl = $default; if (empty($params) || empty($params[0])) { return $aclmap; } if (isset($aclmap['*'])) { $acl = $aclmap['*']; } if (isset($aclmap[$params[0]])) { $acl = $aclmap[$params[0]]; } return $acl; } /** * Internal method to return the a configuration option for the view. These * are equivalent to $config array options passed to the Controller * * @param string $view The view for which we will be fetching a task map * @param array &$configuration The configuration parameters hash array * @param array $params Extra options; key 0 defines the option variable we want to fetch * @param mixed $default Default option; null if not defined * * @return string The setting for the requested option */ protected function getConfig($view, &$configuration, $params, $default = null) { $ret = $default; $config = array(); if (isset($configuration['views']['*']['config'])) { $config = $configuration['views']['*']['config']; } if (isset($configuration['views'][$view]['config'])) { $config = array_merge($config, $configuration['views'][$view]['config']); } if (empty($params) || empty($params[0])) { return $config; } if (isset($config[$params[0]])) { $ret = $config[$params[0]]; } return $ret; } /** * Internal method to return the toolbar infos. * * @param string $view The view for which we will be fetching buttons * @param array &$configuration The configuration parameters hash array * @param array $params Extra options * @param string $default Default option * * @return string The toolbar data for this view */ protected function getToolbar($view, &$configuration, $params, $default = '') { $toolbar = array(); if (isset($configuration['views']['*']) && isset($configuration['views']['*']['toolbar']) && isset($configuration['views']['*']['toolbar']['*'])) { $toolbar = $configuration['views']['*']['toolbar']['*']; } if (isset($configuration['views']['*']) && isset($configuration['views']['*']['toolbar']) && isset($configuration['views']['*']['toolbar'][$params[0]])) { $toolbar = array_merge($toolbar, $configuration['views']['*']['toolbar'][$params[0]]); } if (isset($configuration['views'][$view]) && isset($configuration['views'][$view]['toolbar']) && isset($configuration['views'][$view]['toolbar']['*'])) { $toolbar = array_merge($toolbar, $configuration['views'][$view]['toolbar']['*']); } if (isset($configuration['views'][$view]) && isset($configuration['views'][$view]['toolbar']) && isset($configuration['views'][$view]['toolbar'][$params[0]])) { $toolbar = array_merge($toolbar, $configuration['views'][$view]['toolbar'][$params[0]]); } if (empty($toolbar)) { return $default; } return $toolbar; } } Configuration/Configuration.php000064400000012063152325653670012713 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Configuration; use FOF30\Container\Container; defined('_JEXEC') or die; /** * Reads and parses the fof.xml file in the back-end of a FOF-powered component, * provisioning the data to the rest of the FOF framework * * @since 2.1 */ class Configuration { /** * The component's container * * @var Container */ protected $container = null; /** * Cache of FOF components' configuration variables * * @var array */ public static $configurations = array(); function __construct(Container $c) { $this->container = $c; $this->parseComponent(); } /** * Returns the value of a variable. Variables use a dot notation, e.g. * view.config.whatever where the first part is the domain, the rest of the * parts specify the path to the variable. * * @param string $variable The variable name * @param mixed $default The default value, or null if not specified * * @return mixed The value of the variable */ public function get($variable, $default = null) { static $domains = null; if (is_null($domains)) { $domains = $this->getDomains(); } list($domain, $var) = explode('.', $variable, 2); if (!in_array(ucfirst($domain), $domains)) { return $default; } $class = '\\FOF30\\Configuration\\Domain\\' . ucfirst($domain); /** @var \FOF30\Configuration\Domain\DomainInterface $o */ $o = new $class; return $o->get(self::$configurations[$this->container->componentName], $var, $default); } /** * Parses the configuration of the specified component * * @return void */ protected function parseComponent() { if ($this->container->platform->isCli()) { $order = array('cli', 'backend'); } elseif ($this->container->platform->isBackend()) { $order = array('backend'); } else { $order = array('frontend'); } $order[] = 'common'; $order = array_reverse($order); self::$configurations[$this->container->componentName] = array(); foreach (array(false, true) as $userConfig) { foreach ($order as $area) { $config = $this->parseComponentArea($area, $userConfig); self::$configurations[$this->container->componentName] = array_replace_recursive(self::$configurations[$this->container->componentName], $config); } } } /** * Parses the configuration options of a specific component area * * @param string $area Which area to parse (frontend, backend, cli) * @param bool $userConfig When true the user configuration (fof.user.xml) file will be read * * @return array A hash array with the configuration data */ protected function parseComponentArea($area, $userConfig = false) { $component = $this->container->componentName; // Initialise the return array $ret = array(); // Get the folders of the component $componentPaths = $this->container->platform->getComponentBaseDirs($component); $filesystem = $this->container->filesystem; $path = $componentPaths['admin']; if (isset($this->container['backEndPath'])) { $path = $this->container['backEndPath']; } // This line unfortunately doesn't work with Unit Tests because JPath depends on the JPATH_SITE constant :( // $path = $filesystem->pathCheck($path); // Check that the path exists if (!$filesystem->folderExists($path)) { return $ret; } // Read the filename if it exists $filename = $path . '/fof.xml'; if ($userConfig) { $filename = $path . '/fof.user.xml'; } if (!$filesystem->fileExists($filename) && !file_exists($filename)) { return $ret; } $data = file_get_contents($filename); // Load the XML data in a SimpleXMLElement object $xml = simplexml_load_string($data); if (!($xml instanceof \SimpleXMLElement)) { return $ret; } // Get this area's data $areaData = $xml->xpath('//' . $area); if (empty($areaData)) { return $ret; } $xml = array_shift($areaData); // Parse individual configuration domains $domains = $this->getDomains(); foreach ($domains as $dom) { $class = '\\FOF30\\Configuration\\Domain\\' . ucfirst($dom); if (class_exists($class, true)) { /** @var \FOF30\Configuration\Domain\DomainInterface $o */ $o = new $class; $o->parseDomain($xml, $ret); } } // Finally, return the result return $ret; } /** * Gets a list of the available configuration domain adapters * * @return array A list of the available domains */ protected function getDomains() { static $domains = array(); if (empty($domains)) { $filesystem = $this->container->filesystem; $files = $filesystem->folderFiles(__DIR__ . '/Domain', '.php'); if (!empty($files)) { foreach ($files as $file) { $domain = basename($file, '.php'); if ($domain == 'DomainInterface') { continue; } $domain = preg_replace('/[^A-Za-z0-9]/', '', $domain); $domains[] = $domain; } $domains = array_unique($domains); } } return $domains; } } Container/Exception/NoComponent.php000064400000001065152325653670013414 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Container\Exception; use Exception; defined('_JEXEC') or die; class NoComponent extends \Exception { public function __construct($message = "", $code = 0, Exception $previous = null) { if (empty($message)) { $message = 'No component specified building the Container object'; } if (empty($code)) { $code = 500; } parent::__construct($message, $code, $previous); } } Container/Container.php000064400000057670152325653670011156 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Container; use FOF30\Autoloader\Autoloader; use FOF30\Encrypt\EncryptService; use FOF30\Factory\FactoryInterface; use FOF30\Inflector\Inflector; use FOF30\Params\Params; use FOF30\Platform\Joomla\Filesystem as JoomlaFilesystem; use FOF30\Render\RenderInterface; use FOF30\Template\Template; use FOF30\TransparentAuthentication\TransparentAuthentication as TransparentAuth; use FOF30\View\Compiler\Blade; use Joomla\Registry\Registry; defined('_JEXEC') or die; /** * Dependency injection container for FOF-powered components. * * The properties below (except componentName, bareComponentName and the ones marked with property-read) can be * configured in the fof.xml component configuration file. * * Sample fof.xml: * * <fof> * <common> * <container> * <option name="componentNamespace"><![CDATA[MyCompany\MyApplication]]></option> * <option name="frontEndPath"><![CDATA[%PUBLIC%\components\com_application]]></option> * <option name="factoryClass">magic</option> * </container> * </common> * </fof> * * The paths can use the variables %ROOT%, %PUBLIC%, %ADMIN%, %TMP%, %LOG% i.e. all the path keys returned by Platform's * getPlatformBaseDirs() method in uppercase and surrounded by percent signs. * * * @property string $componentName The name of the component (com_something) * @property string $bareComponentName The name of the component without com_ (something) * @property string $componentNamespace The namespace of the component's classes (\Foobar) * @property string $frontEndPath The absolute path to the front-end files * @property string $backEndPath The absolute path to the back-end files * @property string $thisPath The preferred path. Backend for Admin application, frontend otherwise * @property string $rendererClass The fully qualified class name of the view renderer we'll be using. Must implement FOF30\Render\RenderInterface. * @property string $factoryClass The fully qualified class name of the MVC Factory object, default is FOF30\Factory\BasicFactory. * @property string $platformClass The fully qualified class name of the Platform abstraction object, default is FOF30\Platform\Joomla\Platform. * @property string $mediaVersion A version string for media files in forms. Default: md5 of release version, release date and site secret (if found) * * @property-read \FOF30\Configuration\Configuration $appConfig The application configuration registry * @property-read \FOF30\View\Compiler\Blade $blade The Blade view template compiler engine * @property-read \JDatabaseDriver $db The database connection object * @property-read \FOF30\Dispatcher\Dispatcher $dispatcher The component's dispatcher * @property-read \FOF30\Factory\FactoryInterface $factory The MVC object factory * @property-read \FOF30\Platform\FilesystemInterface $filesystem The filesystem abstraction layer object * @property-read \FOF30\Inflector\Inflector $inflector The English word inflector (pluralise / singularise words etc) * @property-read \FOF30\Params\Params $params The component's params * @property-read \FOF30\Input\Input $input The input object * @property-read \FOF30\Platform\PlatformInterface $platform The platform abstraction layer object * @property-read \FOF30\Render\RenderInterface $renderer The view renderer * @property-read \JSession $session Joomla! session storage * @property-read \FOF30\Template\Template $template The template helper * @property-read TransparentAuth $transparentAuth Transparent authentication handler * @property-read \FOF30\Toolbar\Toolbar $toolbar The component's toolbar * @property-read EncryptService $crypto The component's data encryption service */ class Container extends ContainerBase { /** * Cache of created container instances * * @var array */ protected static $instances = array(); /** * The container SHOULD NEVER be serialised. If this happens, it means that any of the installed version is doing * something REALLY BAD, so let's die and inform the user of what it's going on. */ public function __sleep() { // If the site is in debug mode we die and let the user figure it out if (defined('JDEBUG') && JDEBUG) { $msg = <<< END Something on your site is broken and tries to save the plugin state in the cache. This is a major security issue and will cause your site to not work properly. Go to your site's backend, Global Configuration and set Caching to OFF as a temporary solution. Possible causes: older versions of JoomlaShine templates, JomSocial, BetterPreview and other third party Joomla! extensions. END; die($msg); } // Otherwise we serialise the Container return array('values', 'factories', 'protected', 'frozen', 'raw', 'keys'); } /** * Returns a container instance for a specific component. This method goes through fof.xml to read the default * configuration values for the container. You are advised to use this unless you have a specific reason for * instantiating a Container without going through the fof.xml file. * * Pass the value 'tempInstance' => true in the $values array to get a temporary instance. Otherwise you will get * the cached instance of the previously created container. * * @param string $component The component you want to get a container for, e.g. com_foobar. * @param array $values Container configuration overrides you want to apply. Optional. * @param string $section The application section (site, admin) you want to fetch. Any other value results in auto-detection. * * @return \FOF30\Container\Container */ public static function &getInstance($component, array $values = array(), $section = 'auto') { $tempInstance = false; if (isset($values['tempInstance'])) { $tempInstance = $values['tempInstance']; unset($values['tempInstance']); } if ($tempInstance) { return self::makeInstance($component, $values, $section); } $signature = md5($component . '@' . $section); if (!isset(self::$instances[$signature])) { self::$instances[$signature] = self::makeInstance($component, $values, $section); } return self::$instances[$signature]; } /** * Returns a temporary container instance for a specific component. * * @param string $component The component you want to get a container for, e.g. com_foobar. * @param array $values Container configuration overrides you want to apply. Optional. * @param string $section The application section (site, admin) you want to fetch. Any other value results in auto-detection. * * @return \FOF30\Container\Container */ protected static function &makeInstance($component, array $values = array(), $section = 'auto') { // Try to auto-detect some defaults $tmpConfig = array_merge($values, array('componentName' => $component)); $tmpContainer = new Container($tmpConfig); if (!in_array($section, array('site', 'admin'))) { $section = $tmpContainer->platform->isBackend() ? 'admin' : 'site'; } $appConfig = $tmpContainer->appConfig; // Get the namespace from fof.xml $namespace = $appConfig->get('container.componentNamespace', null); // $values always overrides $namespace and fof.xml if (isset($values['componentNamespace'])) { $namespace = $values['componentNamespace']; } // If there is no namespace set, try to guess it. if (empty($namespace)) { $bareComponent = $component; if (substr($component, 0, 4) == 'com_') { $bareComponent = substr($component, 4); } $namespace = ucfirst($bareComponent); } // Get the default front-end/back-end paths $frontEndPath = $appConfig->get('container.frontEndPath', JPATH_SITE . '/components/' . $component); $backEndPath = $appConfig->get('container.backEndPath', JPATH_ADMINISTRATOR . '/components/' . $component); // Parse path variables if necessary $frontEndPath = $tmpContainer->parsePathVariables($frontEndPath); $backEndPath = $tmpContainer->parsePathVariables($backEndPath); // Apply path overrides if (isset($values['frontEndPath'])) { $frontEndPath = $values['frontEndPath']; } if (isset($values['backEndPath'])) { $backEndPath = $values['backEndPath']; } $thisPath = ($section == 'admin') ? $backEndPath : $frontEndPath; // Get the namespaces for the front-end and back-end parts of the component $frontEndNamespace = '\\' . $namespace . '\\Site\\'; $backEndNamespace = '\\' . $namespace . '\\Admin\\'; // Special case: if the frontend and backend paths are identical, we don't use the Site and Admin namespace // suffixes after $this->componentNamespace (so you may use FOF with JApplicationWeb apps) if ($frontEndPath == $backEndPath) { $frontEndNamespace = '\\' . $namespace . '\\'; $backEndNamespace = '\\' . $namespace . '\\'; } // Do we have to register the component's namespaces with the autoloader? $autoloader = Autoloader::getInstance(); if (!$autoloader->hasMap($frontEndNamespace)) { $autoloader->addMap($frontEndNamespace, $frontEndPath); } if (!$autoloader->hasMap($backEndNamespace)) { $autoloader->addMap($backEndNamespace, $backEndPath); } // Get the Container class name $classNamespace = ($section == 'admin') ? $backEndNamespace : $frontEndNamespace; $class = $classNamespace . 'Container'; // Get the values overrides from fof.xml $values = array_merge(array( 'factoryClass' => '\\FOF30\\Factory\\BasicFactory', 'platformClass' => '\\FOF30\\Platform\\Joomla\\Platform', 'scaffolding' => false, 'saveScaffolding' => false, 'saveControllerScaffolding' => false, 'saveModelScaffolding' => false, 'saveViewScaffolding' => false, 'section' => $section, ), $values); $values = array_merge($values, array( 'componentName' => $component, 'componentNamespace' => $namespace, 'frontEndPath' => $frontEndPath, 'backEndPath' => $backEndPath, 'thisPath' => $thisPath, 'rendererClass' => $appConfig->get('container.rendererClass', null), 'factoryClass' => $appConfig->get('container.factoryClass', $values['factoryClass']), 'platformClass' => $appConfig->get('container.platformClass', $values['platformClass']), 'scaffolding' => $appConfig->get('container.scaffolding', $values['scaffolding']), 'saveScaffolding' => $appConfig->get('container.saveScaffolding', $values['saveScaffolding']), 'saveControllerScaffolding' => $appConfig->get('container.saveControllerScaffolding', $values['saveControllerScaffolding']), 'saveModelScaffolding' => $appConfig->get('container.saveModelScaffolding', $values['saveModelScaffolding']), 'saveViewScaffolding' => $appConfig->get('container.saveViewScaffolding', $values['saveViewScaffolding']), )); if (empty($values['rendererClass'])) { unset ($values['rendererClass']); } $mediaVersion = $appConfig->get('container.mediaVersion', null); if (!empty($mediaVersion)) { $values['mediaVersion'] = $mediaVersion; } unset($appConfig); unset($tmpConfig); unset($tmpContainer); if (class_exists($class, true)) { $container = new $class($values); } else { $container = new Container($values); } return $container; } /** * Public constructor. This does NOT go through the fof.xml file. You are advised to use getInstance() instead. * * @param array $values Overrides for the container configuration and services * * @throws \FOF30\Container\Exception\NoComponent If no component name is specified */ public function __construct(array $values = array()) { // Initialise $this->bareComponentName = ''; $this->componentName = ''; $this->componentNamespace = ''; $this->frontEndPath = ''; $this->backEndPath = ''; $this->thisPath = ''; $this->factoryClass = 'FOF30\\Factory\\BasicFactory'; $this->platformClass = 'FOF30\\Platform\\Joomla\\Platform'; // Try to construct this container object parent::__construct($values); // Make sure we have a component name if (empty($this['componentName'])) { throw new Exception\NoComponent; } $bareComponent = substr($this->componentName, 4); $this['bareComponentName'] = $bareComponent; // Try to guess the component's namespace if (empty($this['componentNamespace'])) { $this->componentNamespace = ucfirst($bareComponent); } else { $this->componentNamespace = trim($this->componentNamespace, '\\'); } // Make sure we have front-end and back-end paths if (empty($this['frontEndPath'])) { $this->frontEndPath = JPATH_SITE . '/components/' . $this->componentName; } if (empty($this['backEndPath'])) { $this->backEndPath = JPATH_ADMINISTRATOR . '/components/' . $this->componentName; } // Get the namespaces for the front-end and back-end parts of the component $frontEndNamespace = '\\' . $this->componentNamespace . '\\Site\\'; $backEndNamespace = '\\' . $this->componentNamespace . '\\Admin\\'; // Special case: if the frontend and backend paths are identical, we don't use the Site and Admin namespace // suffixes after $this->componentNamespace (so you may use FOF with JApplicationWeb apps) if ($this->frontEndPath == $this->backEndPath) { $frontEndNamespace = '\\' . $this->componentNamespace . '\\'; $backEndNamespace = '\\' . $this->componentNamespace . '\\'; } // Do we have to register the component's namespaces with the autoloader? $autoloader = Autoloader::getInstance(); if (!$autoloader->hasMap($frontEndNamespace)) { $autoloader->addMap($frontEndNamespace, $this->frontEndPath); } if (!$autoloader->hasMap($backEndNamespace)) { $autoloader->addMap($backEndNamespace, $this->backEndPath); } // Inflector service if (!isset($this['inflector'])) { $this['inflector'] = function (Container $c) { return new Inflector(); }; } // Filesystem abstraction service if (!isset($this['filesystem'])) { $this['filesystem'] = function (Container $c) { return new JoomlaFilesystem($c); }; } // Platform abstraction service if (!isset($this['platform'])) { if (empty($c['platformClass'])) { $c['platformClass'] = 'FOF30\\Platform\\Joomla\\Platform'; } $this['platform'] = function (Container $c) { $className = $c['platformClass']; return new $className($c); }; } if (empty($this['thisPath'])) { $this['thisPath'] = $this['frontEndPath']; if ($this->platform->isBackend()) { $this['thisPath'] = $this['backEndPath']; } } // MVC Factory service if (!isset($this['factory'])) { $this['factory'] = function (Container $c) { if (empty($c['factoryClass'])) { $c['factoryClass'] = 'FOF30\\Factory\\BasicFactory'; } if (strpos($c['factoryClass'], '\\') === false) { $class = $c->getNamespacePrefix() . 'Factory\\' . $c['factoryClass']; if (class_exists($class)) { $c['factoryClass'] = $class; } else { $c['factoryClass'] = '\\FOF30\\Factory\\' . ucfirst($c['factoryClass']) . 'Factory'; } } if (!class_exists($c['factoryClass'], true)) { $c['factoryClass'] = 'FOF30\\Factory\\BasicFactory'; } $factoryClass = $c['factoryClass']; /** @var FactoryInterface $factory */ $factory = new $factoryClass($c); if (isset($c['scaffolding'])) { $factory->setScaffolding($c['scaffolding']); } if (isset($c['saveScaffolding'])) { $factory->setSaveScaffolding($c['saveScaffolding']); } if (isset($c['saveControllerScaffolding'])) { $factory->setSaveControllerScaffolding($c['saveControllerScaffolding']); } if (isset($c['saveModelScaffolding'])) { $factory->setSaveModelScaffolding($c['saveModelScaffolding']); } if (isset($c['saveViewScaffolding'])) { $factory->setSaveViewScaffolding($c['saveViewScaffolding']); } if (isset($c['section'])) { $factory->setSection($c['section']); } return $factory; }; } // Component Configuration service if (!isset($this['appConfig'])) { $this['appConfig'] = function (Container $c) { $class = $c->getNamespacePrefix() . 'Configuration\\Configuration'; if (!class_exists($class, true)) { $class = '\\FOF30\\Configuration\\Configuration'; } return new $class($c); }; } // Component Params service if (!isset($this['params'])) { $this['params'] = function (Container $c) { return new Params($c); }; } // Blade view template compiler service if (!isset($this['blade'])) { $this['blade'] = function (Container $c) { return new Blade($c); }; } // Database Driver service if (!isset($this['db'])) { $this['db'] = function (Container $c) { return $c->platform->getDbo(); }; } // Request Dispatcher service if (!isset($this['dispatcher'])) { $this['dispatcher'] = function (Container $c) { return $c->factory->dispatcher(); }; } // Component toolbar provider if (!isset($this['toolbar'])) { $this['toolbar'] = function (Container $c) { return $c->factory->toolbar(); }; } // Component toolbar provider if (!isset($this['transparentAuth'])) { $this['transparentAuth'] = function (Container $c) { return $c->factory->transparentAuthentication(); }; } // View renderer if (!isset($this['renderer'])) { $this['renderer'] = function (Container $c) { if (isset($c['rendererClass']) && class_exists($c['rendererClass'])) { $class = $c['rendererClass']; $renderer = new $class($c); if ($renderer instanceof RenderInterface) { return $renderer; } } $filesystem = $c->filesystem; // Try loading the stock renderers shipped with F0F $path = dirname(__FILE__) . '/../Render/'; $renderFiles = $filesystem->folderFiles($path, '.php'); $renderer = null; $priority = 0; if (!empty($renderFiles)) { foreach ($renderFiles as $filename) { if ($filename == 'RenderBase.php') { continue; } if ($filename == 'RenderInterface.php') { continue; } $className = 'FOF30\\Render\\' . basename($filename, '.php'); if (!class_exists($className, true)) { continue; } /** @var RenderInterface $o */ $o = new $className($c); $info = $o->getInformation(); if (!$info->enabled) { continue; } if ($info->priority > $priority) { $priority = $info->priority; $renderer = $o; } } } return $renderer; }; } // Input Access service if (isset($this['input']) && (!(is_object($this['input'])) || !($this['input'] instanceof \FOF30\Input\Input) || !($this['input'] instanceof \JInput)) ) { if (empty($this['input'])) { $this['input'] = array(); } // This swap is necessary to prevent infinite recursion $this['rawInputData'] = array_merge($this['input']); unset($this['input']); $this['input'] = function (Container $c) { $input = new \FOF30\Input\Input($c['rawInputData']); unset($c['rawInputData']); return $input; }; } if (!isset($this['input'])) { $this['input'] = function () { return new \FOF30\Input\Input(); }; } // Session service if (!isset($this['session'])) { $this['session'] = function () { return \JFactory::getSession(); }; } // Template service if (!isset($this['template'])) { $this['template'] = function (Container $c) { return new Template($c); }; } // Media version string if (!isset($this['mediaVersion'])) { $this['mediaVersion'] = $this->getDefaultMediaVersion(); } // Encryption / cryptography service if (!isset($this['crypto'])) { $this['crypto'] = function (Container $c) { return new EncryptService($c); }; } } /** * Get the applicable namespace prefix for a component section. Possible sections: * auto Auto-detect which is the current component section * inverse The inverse area than auto * site Frontend * admin Backend * * @param string $section The section you want to get information for * * @return string The namespace prefix for the component's classes, e.g. \Foobar\Example\Site\ */ public function getNamespacePrefix($section = 'auto') { // Get the namespaces for the front-end and back-end parts of the component $frontEndNamespace = '\\' . $this->componentNamespace . '\\Site\\'; $backEndNamespace = '\\' . $this->componentNamespace . '\\Admin\\'; // Special case: if the frontend and backend paths are identical, we don't use the Site and Admin namespace // suffixes after $this->componentNamespace (so you may use FOF with JApplicationWeb apps) if ($this->frontEndPath == $this->backEndPath) { $frontEndNamespace = '\\' . $this->componentNamespace . '\\'; $backEndNamespace = '\\' . $this->componentNamespace . '\\'; } switch ($section) { default: case 'auto': if ($this->platform->isBackend()) { return $backEndNamespace; } else { return $frontEndNamespace; } break; case 'inverse': if ($this->platform->isBackend()) { return $frontEndNamespace; } else { return $backEndNamespace; } break; case 'site': return $frontEndNamespace; break; case 'admin': return $backEndNamespace; break; } } public function parsePathVariables($path) { $platformDirs = $this->platform->getPlatformBaseDirs(); // root public admin tmp log $search = array_map(function ($x){ return '%' . strtoupper($x) . '%'; }, array_keys($platformDirs)); $replace = array_values($platformDirs); return str_replace($search, $replace, $path); } /** * Gets the default media version string for the component using the component's version and date, as well as the * site's secret key. * * @return string */ protected function getDefaultMediaVersion() { // Initialise $version = '0.0.0'; $date = '0000-00-00'; $secret = ''; // Get the version and date of the component from the manifest cache try { $db = $this->db; $query = $db->getQuery(true) ->select(array( $db->qn('manifest_cache') ))->from($db->qn('#__extensions')) ->where($db->qn('type') . ' = ' . $db->q('component')) ->where($db->qn('name') . ' = ' . $db->q($this->componentName)); $db->setQuery($query); $json = $db->loadResult(); if (class_exists('JRegistry')) { $params = new \JRegistry($json); } else { $params = new Registry($json); } $version = $params->get('version', $version); $date = $params->get('creationDate', $date); } catch (\Exception $e) { } // Get the site's secret try { $app = \JFactory::getApplication(); if (method_exists($app, 'get')) { $secret = $app->get('secret'); } } catch (\Exception $e) { } // Generate the version string return md5($version . $date . $secret); } } Container/ContainerBase.php000064400000001732152325653670011735 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Container; use FOF30\Pimple\Container; defined('_JEXEC') or die; class ContainerBase extends Container { /** * Magic getter for alternative syntax, e.g. $container->foo instead of $container['foo'] * * @param string $name * * @return mixed * * @throws \InvalidArgumentException if the identifier is not defined */ function __get($name) { return $this->offsetGet($name); } /** * Magic setter for alternative syntax, e.g. $container->foo instead of $container['foo'] * * @param string $name The unique identifier for the parameter or object * @param mixed $value The value of the parameter or a closure for a service * * @throws \RuntimeException Prevent override of a frozen service */ function __set($name, $value) { $this->offsetSet($name, $value); } } Controller/Exception/CannotGetName.php000064400000000521152325653700014027 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Controller\Exception; defined('_JEXEC') or die; /** * Exception thrown when we can't get a Controller's name */ class CannotGetName extends \RuntimeException {} Controller/Exception/ItemNotFound.php000064400000000537152325653700013726 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Controller\Exception; defined('_JEXEC') or die; /** * Exception thrown when we can't find the requested item in a read task */ class ItemNotFound extends \RuntimeException {} Controller/Exception/LockedRecord.php000064400000001141152325653700013703 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Controller\Exception; use Exception; defined('_JEXEC') or die; /** * Exception thrown when the provided Model is locked for writing by another user */ class LockedRecord extends \RuntimeException { public function __construct($message = "", $code = 403, Exception $previous = null) { if (empty($message)) { $message = \JText::_('LIB_FOF_CONTROLLER_ERR_LOCKED'); } parent::__construct($message, $code, $previous); } } Controller/Exception/NotADataModel.php000064400000000536152325653700013766 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Controller\Exception; defined('_JEXEC') or die; /** * Exception thrown when the provided Model is not a DataModel */ class NotADataModel extends \InvalidArgumentException {} Controller/Exception/TaskNotFound.php000064400000000564152325653700013732 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Controller\Exception; defined('_JEXEC') or die; /** * Exception thrown when we can't find a suitable method to handle the requested task */ class TaskNotFound extends \InvalidArgumentException {} Controller/Mixin/PredefinedTaskList.php000064400000003620152325653700014221 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Controller\Mixin; use FOF30\Controller\Controller; defined('_JEXEC') or die; /** * Force a Controller to allow access to specific tasks only, no matter which tasks are already defined in this * Controller. * * Include this Trait and then in your constructor do this: * $this->setPredefinedTaskList(['atask', 'anothertask', 'something']); * * WARNING: If you override execute() you will need to copy the logic from this trait's execute() method. */ trait PredefinedTaskList { /** * A list of predefined tasks. Trying to access any other task will result in the first task of this list being * executed instead. * * @var array */ protected $predefinedTaskList = array(); /** * Overrides the execute method to implement the predefined task list feature * * @param string $task The task to execute * * @return mixed The controller task result */ public function execute($task) { if (!in_array($task, $this->predefinedTaskList)) { $task = reset($this->predefinedTaskList); } return parent::execute($task); } /** * Sets the predefined task list and registers the first task in the list as the Controller's default task * * @param array $taskList The task list to register * * @return void */ public function setPredefinedTaskList(array $taskList) { /** @var Controller $this */ // First, unregister all known tasks which are not in the taskList $allTasks = $this->getTasks(); foreach ($allTasks as $task) { if (in_array($task, $taskList)) { continue; } $this->unregisterTask($task); } // Set the predefined task list $this->predefinedTaskList = $taskList; // Set the default task $this->registerDefaultTask(reset($this->predefinedTaskList)); } } Controller/Controller.php000064400000071300152325653700011534 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Controller; use FOF30\Container\Container; use FOF30\Controller\Exception\CannotGetName; use FOF30\Controller\Exception\TaskNotFound; use FOF30\Model\DataModel; use FOF30\Model\Model; use FOF30\View\View; defined('_JEXEC') or die; /** * Class Controller * * A generic MVC controller implementation * * @property-read \FOF30\Input\Input $input The input object (magic __get returns the Input from the Container) */ class Controller { /** * The name of the controller * * @var array */ protected $name = null; /** * The mapped task that was performed. * * @var string */ protected $doTask; /** * Bit mask to enable routing through JRoute on redirects. The value can be: * * 0 = never * 1 = frontend only * 2 = backend only * 3 = always * * @var int */ protected $autoRouting = 0; /** * Should I protect against state bleedover? When this is enabled the default model's state hash will be * automatically set to include the controller name i.e. `com_example.controllerName.modelName.` instead of * `com_example.modelName.`. This will happen ONLY if the preventStateBleedover flag is set, the controller and * model names are different and the model doesn't set its own hash (or override getHash altogether). * * You should only need to enable this feature when you have multiple controllers using the _same_ Model as their * default. For example, if you have a blog component with Latest and Posts Controllers, both using the Posts Model * as their default Model the state variables set in the latest posts page would bleed over to the posts page. This * can include filtering and pagination preferences, resulting in a confusing experience for the user. * * Caveat: if you are using a different Controller class for singular / plural view names you will need to override * getModel() yourself. Otherwise the state of the singular view would be disjointed from the state of the * plural view (since the Controller names are different). That's the reason why this feature is turned off * by default. * * False = same behavior as FOF 3.0.0 to 3.1.1 inclusive. * * @var bool */ protected $preventStateBleedover = false; /** * Redirect message. * * @var string */ protected $message; /** * Redirect message type. * * @var string */ protected $messageType; /** * Array of class methods * * @var array */ protected $methods; /** * The set of search directories for resources (views). * * @var array */ protected $paths; /** * URL for redirection. * * @var string */ protected $redirect; /** * Current or most recently performed task. * * @var string */ protected $task; /** * Array of class methods to call for a given task. * * @var array */ protected $taskMap; /** * Instance container. * * @var Controller */ protected static $instance; /** * The current view name; you can override it in the configuration * * @var string */ protected $view = ''; /** * The current layout; you can override it in the configuration * * @var string */ protected $layout = null; /** * A cached copy of the class configuration parameter passed during initialisation * * @var array */ protected $config = array(); /** * Overrides the name of the view's default model * * @var string */ protected $modelName = null; /** * Overrides the name of the view's default view * * @var string */ protected $viewName = null; /** * An array of Model instances known to this Controller * * @var array[Model] */ protected $modelInstances = array(); /** * An array of View instances known to this Controller * * @var array[View] */ protected $viewInstances = array(); /** * The container attached to this Controller * * @var Container */ protected $container = null; /** * The tasks for which caching should be enabled by default * * @var array */ protected $cacheableTasks = array(); /** * An associative array for required ACL privileges per task. For example: * array( * 'edit' => 'core.edit', * 'jump' => 'foobar.jump', * 'alwaysallow' => 'true', * 'neverallow' => 'false' * ); * * You can use the notation '@task' which means 'apply the same privileges as "task"'. If you create a reference * back to yourself (e.g. 'mytask' => array('@mytask')) it will return TRUE. * * @var array */ protected $taskPrivileges = array(); /** * Enable CSRF protection on selected tasks. The possible values are: * * 0 Disabled; no token checks are performed * 1 Enabled; token checks are always performed * 2 Only on HTML requests and backend; token checks are always performed in the back-end and in the front-end only when format is 'html' * 3 Only on back-end; token checks are performed only in the back-end * * @var integer */ protected $csrfProtection = 2; /** * Public constructor of the Controller class. You can pass the following variables in the $config array: * name string The name of the Controller. Default: auto detect from the class name * default_task string The task to use when none is specified. Default: main * autoRouting int See the autoRouting property * csrfProtection int See the csrfProtection property * viewName string The view name. Default: the same as the controller name * modelName string The model name. Default: the same as the controller name * viewConfig array The configuration overrides for the View. * modelConfig array The configuration overrides for the Model. * * @param Container $container The application container * @param array $config The configuration array * * @return Controller */ public function __construct(Container $container, array $config = array()) { // Initialise $this->methods = array(); $this->message = null; $this->messageType = 'message'; $this->paths = array(); $this->redirect = null; $this->taskMap = array(); // Get a local copy of the container $this->container = $container; // Determine the methods to exclude from the base class. $xMethods = get_class_methods('\\FOF30\\Controller\\Controller'); // Get the public methods in this class using reflection. $r = new \ReflectionClass($this); $rMethods = $r->getMethods(\ReflectionMethod::IS_PUBLIC); foreach ($rMethods as $rMethod) { $mName = $rMethod->getName(); // If the developer screwed up and declared one of the helper method public do NOT make them available as // tasks. if ((substr($mName, 0, 8) == 'onBefore') || (substr($mName, 0, 7) == 'onAfter') || substr($mName, 0, 1) == '_') { continue; } // Add default display method if not explicitly declared. if (!in_array($mName, $xMethods) || $mName == 'display' || $mName == 'main') { $this->methods[] = $mName; // Auto register the methods as tasks. $this->taskMap[$mName] = $mName; } } if (isset($config['name'])) { $this->name = $config['name']; } // Get the default values for the component and view names $this->view = $this->getName(); $this->layout = $this->input->getCmd('layout', null); // If the default task is set, register it as such if (array_key_exists('default_task', $config) && !empty($config['default_task'])) { $this->registerDefaultTask($config['default_task']); } else { $this->registerDefaultTask('main'); } // Cache the config $this->config = $config; // Set any model/view name overrides if (array_key_exists('viewName', $config) && !empty($config['viewName'])) { $this->setViewName($config['viewName']); } if (array_key_exists('modelName', $config) && !empty($config['modelName'])) { $this->setModelName($config['modelName']); } // Apply the autoRouting preference if (array_key_exists('autoRouting', $config)) { $this->autoRouting = (int) $config['autoRouting']; } // Apply the csrfProtection preference if (array_key_exists('csrfProtection', $config)) { $this->csrfProtection = (int) $config['csrfProtection']; } // Apply the preventStateBleedover preference if (array_key_exists('preventStateBleedover', $config)) { $this->preventStateBleedover = (bool) ((int) $config['preventStateBleedover']); } } /** * Magic get method. Handles magic properties: * $this->input mapped to $this->container->input * * @param string $name The property to fetch * * @return mixed|null */ public function __get($name) { // Handle $this->input if ($name == 'input') { return $this->container->input; } // Property not found; raise error $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } /** * Executes a given controller task. The onBefore<task> and onAfter<task> * methods are called automatically if they exist. * * @param string $task The task to execute, e.g. "browse" * * @return null|bool False on execution failure * * @throws TaskNotFound When the task is not found */ public function execute($task) { $this->task = $task; if (!isset($this->taskMap[$task]) && !isset($this->taskMap['__default'])) { throw new TaskNotFound(\JText::sprintf('JLIB_APPLICATION_ERROR_TASK_NOT_FOUND', $task), 404); } $result = $this->triggerEvent('onBeforeExecute', array(&$task)); if ($result === false) { return false; } $eventName = 'onBefore' . ucfirst($task); $result = $this->triggerEvent($eventName); if ($result === false) { return false; } // Do not allow the display task to be directly called if (isset($this->taskMap[$task])) { $doTask = $this->taskMap[$task]; } elseif (isset($this->taskMap['__default'])) { $doTask = $this->taskMap['__default']; } else { $doTask = null; } // Record the actual task being fired $this->doTask = $doTask; $ret = $this->$doTask(); $eventName = 'onAfter' . ucfirst($task); $result = $this->triggerEvent($eventName); if ($result === false) { return false; } $result = $this->triggerEvent('onAfterExecute', array($task)); if ($result === false) { return false; } return $ret; } /** * Default task. Assigns a model to the view and asks the view to render * itself. * * YOU MUST NOT USE THIS TASK DIRECTLY IN A URL. It is supposed to be * used ONLY inside your code. In the URL, use task=browse instead. * * @param bool $cachable Is this view cacheable? * @param bool $urlparams Add your safe URL parameters (see further down in the code) * @param string $tpl The name of the template file to parse * * @return void */ public function display($cachable = false, $urlparams = false, $tpl = null) { $document = $this->container->platform->getDocument(); if ($document instanceof \JDocument) { $viewType = $document->getType(); } else { $viewType = $this->input->getCmd('format', 'html'); } $view = $this->getView(); $view->setTask($this->task); $view->setDoTask($this->doTask); // Get/Create the model if ($model = $this->getModel()) { // Push the model into the view (as default) $view->setDefaultModel($model); } // Set the layout if (!is_null($this->layout)) { $view->setLayout($this->layout); } $conf = $this->container->platform->getConfig(); if ($this->container->platform->isFrontend() && $cachable && ($viewType != 'feed') && ($conf->get('caching') >= 1)) { // Get a JCache object $option = $this->input->get('option', 'com_foobar', 'cmd'); /** @var \JCacheControllerView $cache */ $cache = \JFactory::getCache($option, 'view'); // Set up a cache ID based on component, view, task and user group assignment $user = $this->container->platform->getUser(); if ($user->guest) { $groups = array(); } else { $groups = $user->groups; } $importantParameters = array(); // Set up safe URL parameters if (!is_array($urlparams)) { $urlparams = array( 'option' => 'CMD', 'view' => 'CMD', 'task' => 'CMD', 'format' => 'CMD', 'layout' => 'CMD', 'id' => 'INT', ); } if (is_array($urlparams)) { /** @var \JApplicationCms $app */ $app = \JFactory::getApplication(); $registeredurlparams = null; if (!empty($app->registeredurlparams)) { $registeredurlparams = $app->registeredurlparams; } else { $registeredurlparams = new \stdClass; } foreach ($urlparams as $key => $value) { // Add your safe url parameters with variable type as value {@see JFilterInput::clean()}. $registeredurlparams->$key = $value; // Add the URL-important parameters into the array $importantParameters[$key] = $this->input->get($key, null, $value); } $app->registeredurlparams = $registeredurlparams; } // Create the cache ID after setting the registered URL params, as they are used to generate the ID $cacheId = md5(serialize(array(\JCache::makeId(), $view->getName(), $this->doTask, $groups, $importantParameters))); // Get the cached view or cache the current view $cache->get($view, 'display', $cacheId); } else { // Display without caching $view->display($tpl); } } /** * Alias to the display() task * * @codeCoverageIgnore */ public function main() { $this->display(); } /** * Returns a named Model object * * @param string $name The Model name. If null we'll use the modelName * variable or, if it's empty, the same name as * the Controller * @param array $config Configuration parameters to the Model. If skipped * we will use $this->config * * @return Model The instance of the Model known to this Controller */ public function getModel($name = null, $config = array()) { if (!empty($name)) { $modelName = $name; } elseif (!empty($this->modelName)) { $modelName = $this->modelName; } else { $modelName = $this->view; } if (!array_key_exists($modelName, $this->modelInstances)) { if (empty($config) && isset($this->config['modelConfig'])) { $config = $this->config['modelConfig']; } if (empty($name)) { $config['modelTemporaryInstance'] = true; $controllerName = $this->getName(); if ($controllerName != $modelName) { $config['hash_view'] = $controllerName; } } else { // Other classes are loaded with persistent state disabled and their state/input blanked out $config['modelTemporaryInstance'] = false; $config['modelClearState'] = true; $config['modelClearInput'] = true; } $this->modelInstances[$modelName] = $this->container->factory->model(ucfirst($modelName), $config); } return $this->modelInstances[$modelName]; } /** * Returns a named View object * * @param string $name The Model name. If null we'll use the modelName * variable or, if it's empty, the same name as * the Controller * @param array $config Configuration parameters to the Model. If skipped * we will use $this->config * * @return View The instance of the Model known to this Controller */ public function getView($name = null, $config = array()) { if (!empty($name)) { $viewName = $name; } elseif (!empty($this->viewName)) { $viewName = $this->viewName; } else { $viewName = $this->view; } if (!array_key_exists($viewName, $this->viewInstances)) { if (empty($config) && isset($this->config['viewConfig'])) { $config = $this->config['viewConfig']; } $viewType = $this->input->getCmd('format', 'html'); // Get the model's class name $this->viewInstances[$viewName] = $this->container->factory->view($viewName, $viewType, $config); } return $this->viewInstances[$viewName]; } /** * Set the name of the view to be used by this Controller * * @param string $viewName The name of the view * * @return void */ public function setViewName($viewName) { $this->viewName = $viewName; } /** * Set the name of the model to be used by this Controller * * @param string $modelName The name of the model * * @return void */ public function setModelName($modelName) { $this->modelName = $modelName; } /** * Pushes a named model to the Controller * * @param string $modelName The name of the Model * @param Model $model The actual Model object to push * * @return void */ public function setModel($modelName, Model &$model) { $this->modelInstances[$modelName] = $model; } /** * Pushes a named view to the Controller * * @param string $viewName The name of the View * @param View $view The actual View object to push * * @return void */ public function setView($viewName, View &$view) { $this->viewInstances[$viewName] = $view; } /** * Method to get the controller name * * The controller name is set 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 controller * * @throws CannotGetName If it's impossible to determine the name and it's not set */ public function getName() { if (empty($this->name)) { $r = null; if (!preg_match('/(.*)\\\\Controller\\\\(.*)/i', get_class($this), $r)) { throw new CannotGetName(\JText::_('LIB_FOF_CONTROLLER_ERR_GET_NAME'), 500); } $this->name = $r[2]; } return $this->name; } /** * Get the last task that is being performed or was most recently performed. * * @return string The task that is being performed or was most recently performed. */ public function getTask() { return $this->task; } /** * Gets the available tasks in the controller. * * @return array Array[i] of task names. */ public function getTasks() { return $this->methods; } /** * Redirects the browser or returns false if no redirect is set. * * @return boolean False if no redirect exists. */ public function redirect() { if ($this->redirect) { $this->container->platform->redirect($this->redirect, 301, $this->message, $this->messageType); return true; } return false; } /** * Register the default task to perform if a mapping is not found. * * @param string $method The name of the method in the derived class to perform if a named task is not found. * * @return Controller This object to support chaining. */ public function registerDefaultTask($method) { $this->registerTask('__default', $method); return $this; } /** * Register (map) a task to a method in the class. * * @param string $task The task. * @param string $method The name of the method in the derived class to perform for this task. * * @return Controller This object to support chaining. */ public function registerTask($task, $method) { if (in_array($method, $this->methods)) { $this->taskMap[$task] = $method; } return $this; } /** * Unregister (unmap) a task in the class. * * @param string $task The task. * * @return Controller This object to support chaining. */ public function unregisterTask($task) { unset($this->taskMap[$task]); return $this; } /** * Sets the internal message that is passed with a redirect * * @param string $text Message to display on redirect. * @param string $type Message type. Optional, defaults to 'message'. * * @return string Previous message */ public function setMessage($text, $type = 'message') { $previous = $this->message; $this->message = $text; $this->messageType = $type; return $previous; } /** * Set a URL for browser redirection. * * @param string $url URL to redirect to. * @param string $msg Message to display on redirect. Optional, defaults to value set internally by controller, if any. * @param string $type Message type. Optional, defaults to 'message' or the type set by a previous call to setMessage. * * @return Controller This object to support chaining. */ public function setRedirect($url, $msg = null, $type = null) { // If we're parsing a non-SEF URL decide whether to use JRoute or not if (strpos($url, 'index.php') === 0) { $isAdmin = $this->container->platform->isBackend(); $auto = false; if (($this->autoRouting == 2 || $this->autoRouting == 3) && $isAdmin) { $auto = true; } if (($this->autoRouting == 1 || $this->autoRouting == 3) && !$isAdmin) { $auto = true; } if ($auto) { $url = \JRoute::_($url, false); } } // Set the redirection $this->redirect = $url; if ($msg !== null) { // Controller may have set this directly $this->message = $msg; } // Ensure the type is not overwritten by a previous call to setMessage. if (empty($this->messageType)) { $this->messageType = 'message'; } // If the type is explicitly set, set it. if (!empty($type)) { $this->messageType = $type; } return $this; } /** * Provides CSRF protection through the forced use of a secure token. If the token doesn't match the one in the * session we return false. * * @return bool * * @throws \Exception */ protected function csrfProtection() { static $isCli = null, $isAdmin = null; $platform = $this->container->platform; if (is_null($isCli)) { $isCli = $platform->isCli(); $isAdmin = $platform->isBackend(); } switch ($this->csrfProtection) { // Never case 0: return true; break; // Always case 1: break; // Only back-end and HTML format case 2: if ($isCli) { return true; } elseif (!$isAdmin && ($this->input->get('format', 'html', 'cmd') != 'html')) { return true; } break; // Only back-end case 3: if (!$isAdmin) { return true; } break; } // Check for a session token $token = $this->container->platform->getToken(false); $hasToken = $this->input->get($token, false, 'none') == 1; if (!$hasToken) { $hasToken = $this->input->get('_token', null, 'none') == $token; } if ($hasToken) { $view = $this->input->getCmd('view'); $task = $this->input->getCmd('task'); \JLog::add( "FOF: You are using a legacy session token in (view, task)=($view, $task). Support for legacy tokens will go away. Use form tokens instead.", \JLog::WARNING, 'deprecated' ); } // Check for a form token if (!$hasToken) { $token = $this->container->platform->getToken(true); $hasToken = $this->input->get($token, false, 'none') == 1; if (!$hasToken) { $view = $this->input->getCmd('view'); $task = $this->input->getCmd('task'); \JLog::add( "FOF: You are using the insecure _token form variable in (view, task)=($view, $task). Support for it will go away. Submit a variable with the token as the name and a value of 1 instead.", \JLog::WARNING, 'deprecated' ); $hasToken = $this->input->get('_token', null, 'none') == $token; } } if (!$hasToken) { $platform->raiseError(403, \JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN')); return false; } return true; } /** * Triggers an object-specific event. The event runs both locally –if a suitable method exists– and through the * Joomla! plugin system. A true/false return value is expected. The first false return cancels the event. * * EXAMPLE * Component: com_foobar, Object name: item, Event: onBeforeSomething, Arguments: array(123, 456) * The event calls: * 1. $this->onBeforeSomething(123, 456) * 2. $this->checkACL('@something') if there is no onBeforeSomething and the event starts with onBefore * 3. Joomla! plugin event onComFoobarControllerItemBeforeSomething($this, 123, 456) * * @param string $event The name of the event, typically named onPredicateVerb e.g. onBeforeKick * @param array $arguments The arguments to pass to the event handlers * * @return bool */ protected function triggerEvent($event, array $arguments = array()) { $result = true; // If there is an object method for this event, call it if (method_exists($this, $event)) { switch (count($arguments)) { case 0: $result = $this->{$event}(); break; case 1: $result = $this->{$event}($arguments[0]); break; case 2: $result = $this->{$event}($arguments[0], $arguments[1]); break; case 3: $result = $this->{$event}($arguments[0], $arguments[1], $arguments[2]); break; case 4: $result = $this->{$event}($arguments[0], $arguments[1], $arguments[2], $arguments[3]); break; case 5: $result = $this->{$event}($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4]); break; default: $result = call_user_func_array(array($this, $event), $arguments); break; } } // If there is no handler method perform a simple ACL check elseif (substr($event, 0, 8) == 'onBefore') { $task = substr($event, 8); $result = $this->checkACL('@' . $task); } if ($result === false) { return false; } // All other event handlers live outside this object, therefore they need to be passed a reference to this // objects as the first argument. array_unshift($arguments, $this); // If we have an "on" prefix for the event (e.g. onFooBar) remove it and stash it for later. $prefix = ''; if (substr($event, 0, 2) == 'on') { $prefix = 'on'; $event = substr($event, 2); } // Get the component/model prefix for the event $prefix .= 'Com' . ucfirst($this->container->bareComponentName) . 'Controller'; $prefix .= ucfirst($this->getName()); // The event name will be something like onComFoobarItemsBeforeSomething $event = $prefix . $event; // Call the Joomla! plugins $results = $this->container->platform->runPlugins($event, $arguments); if (!empty($results)) { foreach ($results as $result) { if ($result === false) { return false; } } } return true; } /** * Checks if the current user has enough privileges for the requested ACL area. * * @param string $area The ACL area, e.g. core.manage. * * @return boolean True if the user has the ACL privilege specified */ protected function checkACL($area) { $area = $this->getACLRuleFor($area); if (is_bool($area)) { return $area; } if (in_array(strtolower($area), array('false','0','no','403'))) { return false; } if (in_array(strtolower($area), array('true','1','yes'))) { return true; } if (in_array(strtolower($area), array('guest'))) { return $this->container->platform->getUser()->guest; } if (in_array(strtolower($area), array('user'))) { return !$this->container->platform->getUser()->guest; } if (empty($area)) { return true; } return $this->container->platform->authorise($area, $this->container->componentName); } /** * Resolves @task and &callback notations for ACL privileges * * @param string $area The task notation to resolve * @param array $oldAreas Areas we've already been redirected from, used to detect circular references * * @return mixed The resolved ACL privilege */ protected function getACLRuleFor($area, $oldAreas = array()) { // If it's a ¬ation return the callback result if (substr($area, 0, 1) == '&') { $oldAreas[] = $area; $method = substr($area, 1); // Method not found? Assume true. if (!method_exists($this, $method)) { return true; } $area = $this->$method(); return $this->getACLRuleFor($area, $oldAreas); } // If it's not an @notation return the raw string if (substr($area, 0, 1) != '@') { return $area; } // Get the array index (other task) $index = substr($area, 1); // If the referenced task has no ACL map, return true if (!isset($this->taskPrivileges[$index])) { $index = strtolower($index); if (!isset($this->taskPrivileges[$index])) { return true; } } // Get the new ACL area $newArea = $this->taskPrivileges[$index]; $oldAreas[] = $area; // Circular reference found if (in_array($newArea, $oldAreas)) { return true; } // We've found an ACL privilege. Return it. if (substr($area, 0, 1) != '@') { return $newArea; } // We have another reference. Resolve it. return $this->getACLRuleFor($newArea, $oldAreas); } /** * Returns true if there is a redirect set in the controller * * @return boolean */ public function hasRedirect() { return !empty($this->redirect); } } Controller/DataController.php000064400000117114152325653700012332 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Controller; use FOF30\Container\Container; use FOF30\Controller\Exception\ItemNotFound; use FOF30\Controller\Exception\LockedRecord; use FOF30\Controller\Exception\NotADataModel; use FOF30\Controller\Exception\TaskNotFound; use FOF30\Model\DataModel; use FOF30\View\View; defined('_JEXEC') or die; /** * Database-aware Controller * * @property-read \FOF30\Input\Input $input The input object (magic __get returns the Input from the Container) */ class DataController extends Controller { /** * The tasks for which caching should be enabled by default * * @var array */ protected $cacheableTasks = array('browse', 'read'); /** * Variables that should be taken in account while working with the cache. You can set them in Controller constructor * or inside onBefore* methods * * @var false|array */ protected $cacheParams = false; /** * Do we have a valid XML form? * * @var bool */ protected $hasForm = false; /** * An associative array for required ACL privileges per task. For example: * array( * 'edit' => 'core.edit', * 'jump' => 'foobar.jump', * 'alwaysallow' => 'true', * 'neverallow' => 'false' * ); * * You can use the notation '@task' which means 'apply the same privileges as "task"'. If you create a reference * back to yourself (e.g. 'mytask' => array('@mytask')) it will return TRUE. * * @var array */ protected $taskPrivileges = array( // Special privileges '*editown' => 'core.edit.own', // Privilege required to edit own record // Standard tasks 'add' => 'core.create', 'apply' => '&getACLForApplySave', // Apply task: call the getACLForApplySave method 'archive' => 'core.edit.state', 'cancel' => 'core.edit.state', 'copy' => '@add', // Maps copy ACLs to the add task 'edit' => 'core.edit', 'loadhistory' => '@edit', // Maps loadhistory ACLs to the edit task 'orderup' => 'core.edit.state', 'orderdown' => 'core.edit.state', 'publish' => 'core.edit.state', 'remove' => 'core.delete', 'forceRemove' => 'core.delete', 'save' => '&getACLForApplySave', // Save task: call the getACLForApplySave method 'savenew' => 'core.create', 'saveorder' => 'core.edit.state', 'trash' => 'core.edit.state', 'unpublish' => 'core.edit.state', ); /** * An indexed array of default values for the add task. Since the add task resets the model you can't set these * values directly to the model. Instead, the defaultsForAdd values will be fed to model's bind() after it's reset * and before the session-stored item data is bound to the model object. * * @var array */ protected $defaultsForAdd = array(); /** * Public constructor of the Controller class. You can pass the following variables in the $config array, * on top of what you already have in the base Controller class: * * taskPrivileges array ACL privileges for each task * cacheableTasks array The cache-enabled tasks * * @param Container $container The application container * @param array $config The configuration array */ public function __construct(Container $container, array $config = array()) { parent::__construct($container, $config); // Set up a default model name if none is provided if (empty($this->modelName)) { $this->modelName = $container->inflector->pluralize($this->view); } // Set up a default view name if none is provided if (empty($this->viewName)) { $this->viewName = $container->inflector->pluralize($this->view); } if (isset($config['cacheableTasks'])) { if (!is_array($config['cacheableTasks'])) { $config['cacheableTasks'] = explode(',', $config['cacheableTasks']); $config['cacheableTasks'] = array_map('trim', $config['cacheableTasks']); } $this->cacheableTasks = $config['cacheableTasks']; } if (isset($config['taskPrivileges']) && is_array($config['taskPrivileges'])) { $this->taskPrivileges = array_merge($this->taskPrivileges, $config['taskPrivileges']); } } /** * Executes a given controller task. The onBefore<task> and onAfter<task> methods are called automatically if they * exist. * * If $task == 'default' we will determine the CRUD task to use based on the view name and HTTP verb in the request, * overriding the routing. * * @param string $task The task to execute, e.g. "browse" * * @return null|bool False on execution failure * * @throws TaskNotFound When the task is not found */ public function execute($task) { if ($task == 'default') { $task = $this->getCrudTask(); } return parent::execute($task); } /** * Deal with JSON format: no redirects needed * @param string $task The task being executed * @return boolean True if everything went well */ protected function onAfterExecute($task) { // JSON shouldn't have redirects if ($this->hasRedirect() && $this->input->getCmd('format', 'html') == 'json') { // Error: deal with it in REST api way if ($this->messageType == 'error') { $response = new \JResponseJson($this->message, $this->message, true); echo $response; $this->redirect = false; $this->container->platform->setHeader('Status', 500); return; } else { // Not an error, avoid redirect and display the record(s) $this->redirect = false; return $this->display(); } } return true; } /** * Determines the CRUD task to use based on the view name and HTTP verb used in the request. * * @return string The CRUD task (browse, read, edit, delete) */ protected function getCrudTask() { // By default, a plural view means 'browse' and a singular view means 'edit' $view = $this->input->getCmd('view', null); $task = $this->container->inflector->isPlural($view) ? 'browse' : 'edit'; // If the task is 'edit' but there's no logged in user switch to a 'read' task if (($task == 'edit') && !$this->container->platform->getUser()->id) { $task = 'read'; } // Check if there is an id passed in the request $id = $this->input->get('id', null, 'int'); if ($id == 0) { $ids = $this->input->get('ids', array(), 'array'); if (!empty($ids)) { $id = array_shift($ids); } } // Get the request HTTP verb $requestMethod = 'GET'; if (isset($_SERVER['REQUEST_METHOD'])) { $requestMethod = strtoupper($_SERVER['REQUEST_METHOD']); } // Alter the task based on the verb switch ($requestMethod) { // POST and PUT result in a record being saved; no ID means creating a new record case 'POST': case 'PUT': $task = 'save'; break; // DELETE results in a record being deleted, as long as there is an ID case 'DELETE': if ($id) { $task = 'remove'; } break; // GET results in browse, edit or add depending on the ID case 'GET': default: // If it's an edit without an ID or ID=0, it's really an add if (($task == 'edit') && ($id == 0)) { $task = 'add'; } break; } return $task; } /** * Checks if the current user has enough privileges for the requested ACL area. This overridden method supports * asset tracking as well. * * @param string $area The ACL area, e.g. core.manage * * @return boolean True if the user has the ACL privilege specified */ protected function checkACL($area) { $area = $this->getACLRuleFor($area); $result = parent::checkACL($area); // Check if we're dealing with ids $ids = null; // First, check if there is an asset for this record /** @var DataModel $model */ $model = $this->getModel(); $ids = null; if (is_object($model) && ($model instanceof DataModel) && $model->isAssetsTracked()) { $ids = $this->getIDsFromRequest($model, false); } // No IDs tracked, return parent's result if (empty($ids)) { return $result; } // Asset tracking if (!is_array($ids)) { $ids = array($ids); } $resource = $this->container->inflector->singularize($this->view); $isEditState = ($area == 'core.edit.state'); foreach ($ids as $id) { $asset = $this->container->componentName . '.' . $resource . '.' . $id; // Dedicated permission found, check it! $platform = $this->container->platform; if ($platform->authorise($area, $asset) ) { return true; } // Fallback on edit.own, if not edit.state. First test if the permission is available. $editOwn = $this->getACLRuleFor('@*editown'); if ((!$isEditState) && ($platform->authorise($editOwn, $asset))) { $model->load($id); if (!$model->hasField('created_by')) { return false; } // Now test the owner is the user. $owner_id = (int) $model->getFieldValue('created_by', null); // If the owner matches 'me' then do the test. if ($owner_id == $platform->getUser()->id) { return true; } return false; } } // No result found? Not authorised. return false; } /** * Returns a named View object * * @param string $name The Model name. If null we'll use the modelName * variable or, if it's empty, the same name as * the Controller * @param array $config Configuration parameters to the Model. If skipped * we will use $this->config * * @return View The instance of the Model known to this Controller */ public function getView($name = null, $config = array()) { if (!empty($name)) { $viewName = $name; } elseif (!empty($this->viewName)) { $viewName = $this->viewName; } else { $viewName = $this->view; } if (!array_key_exists($viewName, $this->viewInstances)) { if (empty($config) && isset($this->config['viewConfig'])) { $config = $this->config['viewConfig']; } $viewType = $this->input->getCmd('format', 'html'); if (($viewType == 'html') && $this->hasForm) { $viewType = 'form'; } // Get the model's class name $this->viewInstances[$viewName] = $this->container->factory->view($viewName, $viewType, $config); } return $this->viewInstances[$viewName]; } /** * Implements a default browse task, i.e. read a bunch of records and send * them to the browser. * * @return void */ public function browse() { // Initialise the savestate $saveState = $this->input->get('savestate', -999, 'int'); if ($saveState == -999) { $saveState = true; } $this->getModel()->savestate($saveState); // Apply the Form name $formName = 'form.default'; if (!empty($this->layout)) { $formName = 'form.' . $this->layout; } $this->getModel()->setFormName($formName); // Do we have a _valid_ form? $form = $this->getModel()->getForm(); if ($form !== false) { $this->hasForm = true; if (empty($this->layout)) { $this->layout = 'default'; } } // Display the view $this->display(in_array('browse', $this->cacheableTasks), $this->cacheParams); } /** * Single record read. The id set in the request is passed to the model and * then the item layout is used to render the result. * * @return void * * @throws ItemNotFound When the item is not found */ public function read() { // Load the model /** @var DataModel $model */ $model = $this->getModel()->savestate(false); // If there is no record loaded, try loading a record based on the id passed in the input object if (!$model->getId()) { $ids = $this->getIDsFromRequest($model, true); if ($model->getId() != reset($ids)) { $key = strtoupper($this->container->componentName . '_ERR_' . $model->getName() . '_NOTFOUND'); throw new ItemNotFound(\JText::_($key), 404); } } // Set the layout to item, if it's not set in the URL if (empty($this->layout)) { $this->layout = 'item'; } elseif ($this->layout == 'default') { $this->layout = 'item'; } // Apply the Form name $formName = 'form.' . $this->layout; $this->getModel()->setFormName($formName); // Do we have a _valid_ form? $form = $this->getModel()->getForm($model); if ($form !== false) { $this->hasForm = true; } // Display the view $this->display(in_array('read', $this->cacheableTasks), $this->cacheParams); } /** * Single record add. The form layout is used to present a blank page. * * @return void */ public function add() { // Load and reset the model $model = $this->getModel()->savestate(false); $model->reset(); // Set the layout to form, if it's not set in the URL if (empty($this->layout)) { $this->layout = 'form'; } elseif ($this->layout == 'default') { $this->layout = 'form'; } if (!empty($this->defaultsForAdd)) { $model->bind($this->defaultsForAdd); } // Get temporary data from the session, set if the save failed and we're redirected back here $sessionKey = $this->viewName . '.savedata'; $itemData = $this->container->platform->getSessionVar($sessionKey, null, $this->container->componentName); $this->container->platform->setSessionVar($sessionKey, null, $this->container->componentName); if (!empty($itemData)) { $model->bind($itemData); } // Apply the Form name $formName = 'form.form'; if (!empty($this->layout)) { $formName = 'form.' . $this->layout; } $this->getModel()->setFormName($formName); // Do we have a _valid_ form? $form = $this->getModel()->getForm($model); if ($form !== false) { $this->hasForm = true; } // Display the view $this->display(in_array('add', $this->cacheableTasks), $this->cacheParams); } /** * Single record edit. The ID set in the request is passed to the model, * then the form layout is used to edit the result. * * @return void */ public function edit() { // Load the model /** @var DataModel $model */ $model = $this->getModel()->savestate(false); if (!$model->getId()) { $this->getIDsFromRequest($model, true); } $userId = $this->container->platform->getUser()->id; try { if ($model->isLocked($userId)) { $model->checkIn($userId); } $model->lock(); } catch (\Exception $e) { // Redirect on error if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName.'&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url, $e->getMessage(), 'error'); return; } // Set the layout to form, if it's not set in the URL if (empty($this->layout)) { $this->layout = 'form'; } elseif ($this->layout == 'default') { $this->layout = 'form'; } // Get temporary data from the session, set if the save failed and we're redirected back here $sessionKey = $this->viewName . '.savedata'; $itemData = $this->container->platform->getSessionVar($sessionKey, null, $this->container->componentName); $this->container->platform->setSessionVar($sessionKey, null, $this->container->componentName); if (!empty($itemData)) { $model->bind($itemData); } // Apply the Form name $formName = 'form.' . $this->layout; $this->getModel()->setFormName($formName); // Do we have a _valid_ form? $form = $this->getModel()->getForm($model); if ($form !== false) { $this->hasForm = true; } // Display the view $this->display(in_array('edit', $this->cacheableTasks), $this->cacheParams); } /** * Save the incoming data and then return to the Edit task * * @return void */ public function apply() { // CSRF prevention $this->csrfProtection(); // Redirect to the edit task if (!$this->applySave()) { return; } $id = $this->input->get('id', 0, 'int'); $textKey = strtoupper($this->container->componentName . '_LBL_' . $this->container->inflector->singularize($this->view) . '_SAVED'); if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->view . '&task=edit&id=' . $id . $this->getItemidURLSuffix(); $this->setRedirect($url, \JText::_($textKey)); } /** * Duplicates selected items * * @return void */ public function copy() { // CSRF prevention $this->csrfProtection(); $model = $this->getModel()->savestate(false); $ids = $this->getIDsFromRequest($model, true); $error = null; try { $status = true; foreach ($ids as $id) { $model->find($id); $model->copy(); } } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $textKey = strtoupper($this->container->componentName . '_LBL_' . $this->container->inflector->singularize($this->view) . '_COPIED'); $this->setRedirect($url, \JText::_($textKey)); } } /** * Save the incoming data and then return to the Browse task * * @return void */ public function save() { // CSRF prevention $this->csrfProtection(); if (!$this->applySave()) { return; } $textKey = strtoupper($this->container->componentName . '_LBL_' . $this->container->inflector->singularize($this->view) . '_SAVED'); if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url, \JText::_($textKey)); } /** * Save the incoming data and then return to the Add task * * @return bool */ public function savenew() { // CSRF prevention $this->csrfProtection(); if (!$this->applySave()) { return; } $textKey = strtoupper($this->container->componentName . '_LBL_' . $this->container->inflector->singularize($this->view) . '_SAVED'); if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->singularize($this->view) . '&task=add' . $this->getItemidURLSuffix(); $this->setRedirect($url, \JText::_($textKey)); } /** * Save the incoming data as a copy of the given model and then redirect to the copied object edit view * * @return bool */ public function save2copy() { // CSRF prevention $this->csrfProtection(); $model = $this->getModel()->savestate(false); $ids = $this->getIDsFromRequest($model, true); $data = $this->input->getData(); unset($data[$model->getIdFieldName()]); $error = null; try { $status = true; foreach ($ids as $id) { $model->find($id); $model = $model->copy($data); } } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : $url = 'index.php?option=' . $this->container->componentName . '&view=' . $this->view . '&task=edit&id=' . $model->getId() . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $textKey = strtoupper($this->container->componentName . '_LBL_' . $this->container->inflector->singularize($this->view) . '_COPIED'); $this->setRedirect($url, \JText::_($textKey)); } } /** * Cancel the edit, check in the record and return to the Browse task * * @return void */ public function cancel() { $model = $this->getModel()->tmpInstance()->savestate(false); if (!$model->getId()) { $this->getIDsFromRequest($model, true); } if ($model->getId()) { $userId = $this->container->platform->getUser()->id; if ($model->isLocked($userId)) { try { $model->checkIn($userId); } catch (LockedRecord $e) { // Redirect to the display task if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url, $e->getMessage(), 'error'); } } $model->unlock(); } // Remove any saved data $sessionKey = $this->viewName . '.savedata'; $this->container->platform->setSessionVar($sessionKey, null, $this->container->componentName); // Redirect to the display task if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url); } /** * Publish (set enabled = 1) an item. * * @return void */ public function publish() { // CSRF prevention $this->csrfProtection(); $model = $this->getModel()->savestate(false); $ids = $this->getIDsFromRequest($model, false); $error = false; try { $status = true; foreach ($ids as $id) { $model->find($id); $userId = $this->container->platform->getUser()->id; if ($model->isLocked($userId)) { $model->checkIn($userId); } $model->publish(); } } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $this->setRedirect($url); } } /** * Unpublish (set enabled = 0) an item. * * @return void */ public function unpublish() { // CSRF prevention $this->csrfProtection(); $model = $this->getModel()->savestate(false); $ids = $this->getIDsFromRequest($model, false); $error = null; try { $status = true; foreach ($ids as $id) { $model->find($id); $userId = $this->container->platform->getUser()->id; if ($model->isLocked($userId)) { $model->checkIn($userId); } $model->unpublish(); } } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $this->setRedirect($url); } } /** * Archive (set enabled = 2) an item. * * @return void */ public function archive() { // CSRF prevention $this->csrfProtection(); $model = $this->getModel()->savestate(false); $ids = $this->getIDsFromRequest($model, false); $error = null; try { $status = true; foreach ($ids as $id) { $model->find($id); $userId = $this->container->platform->getUser()->id; if ($model->isLocked($userId)) { $model->checkIn($userId); } $model->archive(); } } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $this->setRedirect($url); } } /** * Trash (set enabled = -2) an item. * * @return void */ public function trash() { // CSRF prevention $this->csrfProtection(); $model = $this->getModel()->savestate(false); $ids = $this->getIDsFromRequest($model, false); $error = null; try { $status = true; foreach ($ids as $id) { $model->find($id); $userId = $this->container->platform->getUser()->id; if ($model->isLocked($userId)) { $model->checkIn($userId); } $model->trash(); } } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $this->setRedirect($url); } } /** * Check in (unlock) items * * @return void */ public function checkin() { // CSRF prevention $this->csrfProtection(); $model = $this->getModel()->savestate(false); $ids = $this->getIDsFromRequest($model, false); $error = null; try { $status = true; foreach ($ids as $id) { $model->find($id); $model->checkIn(); } } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $this->setRedirect($url); } } /** * Saves the order of the items * * @return void */ public function saveorder() { // CSRF prevention $this->csrfProtection(); $type = null; $msg = null; $model = $this->getModel()->savestate(false); $ids = $this->getIDsFromRequest($model, false); $orders = $this->input->get('order', array(), 'array'); // Before saving the order, I have to check I the table really supports the ordering feature if(!$model->hasField('ordering')) { $msg = sprintf('%s does not support ordering.', $model->getTableName()); $type = 'error'; } else { $ordering = $model->getFieldAlias('ordering'); // Several methods could throw exceptions, so let's wrap everything in a try-catch try { if ($n = count($ids)) { for ($i = 0; $i < $n; $i++) { $item = $model->find($ids[$i]); $neworder = (int)$orders[$i]; if (!($item instanceof DataModel)) { continue; } if ($item->getId() == $ids[$i]) { $item->$ordering = $neworder; $userId = $this->container->platform->getUser()->id; if ($model->isLocked($userId)) { $model->checkIn($userId); } $model->save($item); } } } $model->reorder(); } catch(\Exception $e) { $msg = $e->getMessage(); $type = 'error'; } } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url, $msg, $type); } /** * Moves selected items one position down the ordering list * * @return void */ public function orderdown() { // CSRF prevention $this->csrfProtection(); $model = $this->getModel()->savestate(false); if (!$model->getId()) { $this->getIDsFromRequest($model, true); } $error = null; try { $userId = $this->container->platform->getUser()->id; if ($model->isLocked($userId)) { $model->checkIn($userId); } $model->move(1); $status = true; } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $this->setRedirect($url); } } /** * Moves selected items one position up the ordering list * * @return void */ public function orderup() { // CSRF prevention $this->csrfProtection(); $model = $this->getModel()->savestate(false); if (!$model->getId()) { $this->getIDsFromRequest($model, true); } $error = null; try { $userId = $this->container->platform->getUser()->id; if ($model->isLocked($userId)) { $model->checkIn($userId); } $model->move(-1); $status = true; } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $this->setRedirect($url); } } /** * Delete or trash selected item(s). The model's softDelete flag determines if the items should be trashed (enabled * state changed to -2) or deleted (completely removed from database) * * @return void */ public function remove() { $this->deleteOrTrash(false); } /** * Deletes the selected item(s). Unlike remove() this method will force delete the record (completely removed from * database) * * @return void */ public function forceRemove() { $this->deleteOrTrash(true); } protected function deleteOrTrash($forceDelete = false) { // CSRF prevention $this->csrfProtection(); $model = $this->getModel()->savestate(false); $ids = $this->getIDsFromRequest($model, false); $error = null; try { $status = true; foreach ($ids as $id) { $model->find($id); $userId = $this->container->platform->getUser()->id; if ($model->isLocked($userId)) { $model->checkIn($userId); } if ($forceDelete) { $model->forceDelete(); } else { $model->delete(); } } } catch (\Exception $e) { $status = false; $error = $e->getMessage(); } // Redirect if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); if (!$status) { $this->setRedirect($url, $error, 'error'); } else { $textKey = strtoupper($this->container->componentName . '_LBL_' . $this->container->inflector->singularize($this->view) . '_DELETED'); $this->setRedirect($url, \JText::_($textKey)); } } /** * Common method to handle apply and save tasks * * @return bool True on success */ protected function applySave() { // Load the model $model = $this->getModel()->savestate(false); if (!$model->getId()) { $this->getIDsFromRequest($model, true); } $userId = $this->container->platform->getUser()->id; $id = $model->getId(); $data = $this->input->getData(); if ($model->isLocked($userId)) { try { $model->checkIn($userId); } catch (LockedRecord $e) { // Redirect to the display task if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } $eventName = 'onAfterApplySaveError'; $result = $this->triggerEvent($eventName, array(&$data, $id, $e)); $url = !empty($customURL) ? $customURL : 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); $this->setRedirect($url, $e->getMessage(), 'error'); return false; } } // Set the layout to form, if it's not set in the URL if (is_null($this->layout)) { $this->layout = 'form'; } // Apply the Form name $formName = 'form.' . $this->layout; $this->getModel()->setFormName($formName); // Save the data $status = true; $error = null; try { $eventName = 'onBeforeApplySave'; $result = $this->triggerEvent($eventName, array(&$data)); if ($id != 0) { // Try to check-in the record if it's not a new one $model->unlock(); } // Save the data $model->save($data); $eventName = 'onAfterApplySave'; $result = $this->triggerEvent($eventName, array(&$data, $model->getId())); $this->input->set('id', $model->getId()); } catch (\Exception $e) { $status = false; $error = $e->getMessage(); $eventName = 'onAfterApplySaveError'; $result = $this->triggerEvent($eventName, array(&$data, $model->getId(), $e)); } if (!$status) { // Cache the item data in the session. We may need to reuse them if the save fails. $itemData = $model->getData(); $sessionKey = $this->viewName . '.savedata'; $this->container->platform->setSessionVar($sessionKey, $itemData, $this->container->componentName); // Redirect on error $id = $model->getId(); if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } if (!empty($customURL)) { $url = $customURL; } elseif ($id != 0) { $url = 'index.php?option=' . $this->container->componentName . '&view=' . $this->view . '&task=edit&id=' . $id . $this->getItemidURLSuffix(); } else { $url = 'index.php?option=' . $this->container->componentName . '&view=' . $this->view . '&task=add' . $this->getItemidURLSuffix(); } $this->setRedirect($url, $error, 'error'); } else { $sessionKey = $this->viewName . '.savedata'; $this->container->platform->setSessionVar($sessionKey, null, $this->container->componentName); } return $status; } /** * Returns a named Model object. Makes sure that the Model is a database-aware model, throwing an exception * otherwise, when $name is null. * * @param string $name The Model name. If null we'll use the modelName * variable or, if it's empty, the same name as * the Controller * @param array $config Configuration parameters to the Model. If skipped * we will use $this->config * * @return DataModel The instance of the Model known to this Controller * * @throws NotADataModel When the model type doesn't match our expectations */ public function getModel($name = null, $config = array()) { $model = parent::getModel($name, $config); if (is_null($name) && !($model instanceof DataModel)) { throw new NotADataModel('Model ' . get_class($model) . ' is not a database-aware Model'); } return $model; } /** * Gets the list of IDs from the request data * * @param DataModel $model The model where the record will be loaded * @param bool $loadRecord When true, the record matching the *first* ID found will be loaded into $model * * @return array */ public function getIDsFromRequest(DataModel &$model, $loadRecord = true) { // Get the ID or list of IDs from the request or the configuration $cid = $this->input->get('cid', array(), 'array'); $id = $this->input->getInt('id', 0); $kid = $this->input->getInt($model->getIdFieldName(), 0); $ids = array(); if (is_array($cid) && !empty($cid)) { $ids = $cid; } else { if (empty($id)) { if(!empty($kid)) { $ids = array($kid); } } else { $ids = array($id); } } if ($loadRecord && !empty($ids)) { $id = reset($ids); $model->find(array('id' => $id)); } return $ids; } /** * Method to load a row from version history * * @return boolean True if the content history is reverted, false otherwise * * @since 2.2 */ public function loadhistory() { $model = $this->getModel(); $model->lock(); $historyId = $this->input->get('version_id', null, 'integer'); $alias = $this->container->componentName . '.' . $this->view; $returnUrl = 'index.php?option=' . $this->container->componentName . '&view=' . $this->container->inflector->pluralize($this->view) . $this->getItemidURLSuffix(); if ($customURL = $this->input->getBase64('returnurl', '')) { $customURL = base64_decode($customURL); } if(!empty($customURL)) { $returnUrl = $customURL; } try { $model->loadhistory($historyId, $alias); } catch (\Exception $e) { $this->setRedirect($returnUrl, $e->getMessage(), 'error'); $model->unlock(); return false; } // Access check. if (!$this->checkACL('@loadhistory')) { $this->setRedirect($returnUrl, \JText::_('JLIB_APPLICATION_ERROR_EDIT_NOT_PERMITTED'), 'error'); $model->unlock(); return false; } $model->store(); $this->setRedirect($returnUrl, \JText::sprintf('JLIB_APPLICATION_SUCCESS_LOAD_HISTORY', $model->getState('save_date'), $model->getState('version_note'))); return true; } /** * Gets a URL suffix with the Itemid parameter. If it's not the front-end of the site, or if * there is no Itemid set it returns an empty string. * * @return string The &Itemid=123 URL suffix, or an empty string if Itemid is not applicable */ public function getItemidURLSuffix() { if ($this->container->platform->isFrontend() && ($this->input->getCmd('Itemid', 0) != 0)) { return '&Itemid=' . $this->input->getInt('Itemid', 0); } else { return ''; } } /** * Gets the applicable ACL privilege for the apply and save tasks. The value returned is: * - @add if the record's ID is empty / record doesn't exist * - True if the ACL privilege of the edit task (@edit) is allowed * - @editown if the owner of the record (field user_id, userid or user) is the same as the logged in user * - False if the record is not owned by the logged in user and the user doesn't have the @edit privilege * * @return bool|string */ protected function getACLForApplySave() { $model = $this->getModel(); if (!$model->getId()) { $this->getIDsFromRequest($model, true); } $id = $model->getId(); if (!$id) { return '@add'; } if ($this->checkACL('@edit')) { return true; } $user = $this->container->platform->getUser(); $uid = 0; if ($model->hasField('user_id')) { $uid = $model->getFieldValue('user_id'); } elseif ($model->hasField('userid')) { $uid = $model->getFieldValue('userid'); } elseif ($model->hasField('user')) { $uid = $model->getFieldValue('user'); } if (!empty($uid) && !$user->guest && ($user->id == $uid)) { return '@editown'; } return false; } } Database/Installer.php000064400000056407152325653700010742 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Database; use JDatabaseDriver; use SimpleXMLElement; use Exception; defined('_JEXEC') or die; class Installer { /** @var JDatabaseDriver The database connector object */ private $db = null; /** @var string The directory where the XML schema files are stored */ private $xmlDirectory = null; /** @var string Force a specific **absolute** file path for the XML schema file */ private $forcedFile = null; /** @var array Internal cache for table list */ protected static $allTables = array(); /** * Public constructor * * @param JDatabaseDriver $db The database driver we're going to use to install the tables * @param string $directory The directory holding the XML schema update files * * @param array $config The configuration array */ public function __construct(JDatabaseDriver $db, $directory) { $this->db = $db; $this->xmlDirectory = $directory; } /** * Sets the directory where XML schema files are stored * * @param string $xmlDirectory * * @codeCoverageIgnore */ public function setXmlDirectory($xmlDirectory) { $this->xmlDirectory = $xmlDirectory; } /** * Returns the directory where XML schema files are stored * * @return string * * @codeCoverageIgnore */ public function getXmlDirectory() { return $this->xmlDirectory; } /** * Returns the absolute path to the forced XML schema file * * @return string * * @codeCoverageIgnore */ public function getForcedFile() { return $this->forcedFile; } /** * Sets the absolute path to an XML schema file which will be read no matter what. Set to a blank string to let the * Installer class auto-detect your schema file based on your database type. * * @param string $forcedFile * * @codeCoverageIgnore */ public function setForcedFile($forcedFile) { $this->forcedFile = $forcedFile; } /** * Clears the internal table list cache * * @return void */ public function nukeCache() { static::$allTables = array(); } /** * Creates or updates the database schema * * @return void * * @throws Exception When a database query fails and it doesn't have the canfail flag */ public function updateSchema() { // Get the schema XML file $xml = $this->findSchemaXml(); if (empty($xml)) { return; } // Make sure there are SQL commands in this file if (!$xml->sql) { return; } // Walk the sql > action tags to find all tables /** @var SimpleXMLElement $actions */ $actions = $xml->sql->children(); /** * The meta/autocollation node defines if I should automatically apply the correct collation (utf8 or utf8mb4) * to the database tables managed by the schema updater. When enabled (default) the queries are automatically * converted to the correct collation (utf8mb4_unicode_ci or utf8_general_ci) depending on whether your Joomla! * and MySQL server support Multibyte UTF-8 (UTF8MB4). Moreover, if UTF8MB4 is supported, all CREATE TABLE * queries are analyzed and the tables referenced in them are auto-converted to the proper utf8mb4 collation. */ $autoCollationConversion = true; if ($xml->meta->autocollation) { $value = (string) $xml->meta->autocollation; $value = trim($value); $value = strtolower($value); $autoCollationConversion = in_array($value, array('true', '1', 'on', 'yes')); } $hasUtf8mb4Support = method_exists($this->db, 'hasUTF8mb4Support') && $this->db->hasUTF8mb4Support(); $tablesToConvert = array(); // If we have an uppercase db prefix we can expect CREATE TABLE fail because we cannot detect reliably // the existence of database tables. See https://github.com/joomla/joomla-cms/issues/10928#issuecomment-228549658 $prefix = $this->db->getPrefix(); $canFailCreateTable = preg_match('/[A-Z]/', $prefix); /** @var SimpleXMLElement $action */ foreach ($actions as $action) { // Get the attributes $attributes = $action->attributes(); // Get the table / view name $table = $attributes->table ? (string) $attributes->table : ''; if (empty($table)) { continue; } // Am I allowed to let this action fail? $canFailAction = $attributes->canfail ? $attributes->canfail : 0; // Evaluate conditions $shouldExecute = true; /** @var SimpleXMLElement $node */ foreach ($action->children() as $node) { if ($node->getName() == 'condition') { // Get the operator $operator = $node->attributes()->operator ? (string)$node->attributes()->operator : 'and'; $operator = empty($operator) ? 'and' : $operator; $condition = $this->conditionMet($table, $node); switch ($operator) { case 'not': $shouldExecute = $shouldExecute && !$condition; break; case 'or': $shouldExecute = $shouldExecute || $condition; break; case 'nor': $shouldExecute = !$shouldExecute && !$condition; break; case 'xor': $shouldExecute = ($shouldExecute xor $condition); break; case 'maybe': $shouldExecute = $condition ? true : $shouldExecute; break; default: $shouldExecute = $shouldExecute && $condition; break; } } // DO NOT USE BOOLEAN SHORT CIRCUIT EVALUATION! // if (!$shouldExecute) break; } // Do I have to only collect the tables from CREATE TABLE queries? $onlyCollectTables = !$shouldExecute && $autoCollationConversion && $hasUtf8mb4Support; // Make sure all conditions are met OR I have to collect tables from CREATE TABLE queries. if (!$shouldExecute && !$onlyCollectTables) { continue; } // Execute queries foreach ($action->children() as $node) { if ($node->getName() == 'query') { $query = (string) $node; if ($autoCollationConversion && $hasUtf8mb4Support) { $this->extractTablesToConvert($query, $tablesToConvert); } // If we're only collecting tables do not run the queries if ($onlyCollectTables) { continue; } $canFail = $node->attributes->canfail ? (string)$node->attributes->canfail : $canFailAction; if (is_string($canFail)) { $canFail = strtoupper($canFail); } $canFail = (in_array($canFail, array(true, 1, 'YES', 'TRUE'))); // Do I need to automatically convert the collation of all CREATE / ALTER queries? if ($autoCollationConversion) { if ($hasUtf8mb4Support) { // We have UTF8MB4 support. Convert all queries to UTF8MB4. $query = $this->convertUtf8QueryToUtf8mb4($query); } else { // We do not have UTF8MB4 support. Convert all queries to plain old UTF8. $query = $this->convertUtf8mb4QueryToUtf8($query); } } $this->db->setQuery($query); try { $this->db->execute(); } catch (Exception $e) { // Special consideration for CREATE TABLE commands on uppercase prefix databases. if ($canFailCreateTable && stripos($query, 'CREATE TABLE') !== false) { $canFail = true; } // If we are not allowed to fail, throw back the exception we caught if (!$canFail) { throw $e; } } } } } // Auto-convert the collation of tables if we are told to do so, have utf8mb4 support and a list of tables. if ($autoCollationConversion && $hasUtf8mb4Support && !empty($tablesToConvert)) { $this->convertTablesToUtf8mb4($tablesToConvert); } } /** * Uninstalls the database schema * * @return void */ public function removeSchema() { // Get the schema XML file $xml = $this->findSchemaXml(); if (empty($xml)) { return; } // Make sure there are SQL commands in this file if (!$xml->sql) { return; } // Walk the sql > action tags to find all tables $tables = array(); /** @var SimpleXMLElement $actions */ $actions = $xml->sql->children(); /** @var SimpleXMLElement $action */ foreach ($actions as $action) { $attributes = $action->attributes(); $tables[] = (string)$attributes->table; } // Simplify the tables list $tables = array_unique($tables); // Start dropping tables foreach ($tables as $table) { try { $this->db->dropTable($table); } catch (Exception $e) { // Do not fail if I can't drop the table } } } /** * Find an suitable schema XML file for this database type and return the SimpleXMLElement holding its information * * @return null|SimpleXMLElement Null if no suitable schema XML file is found */ protected function findSchemaXml() { $xml = null; // Do we have a forced file? if ($this->forcedFile) { $xml = $this->openAndVerify($this->forcedFile); if ($xml !== false) { return $xml; } } class_exists('\\JFolder') || \JLoader::import('joomla.filesystem.folder'); // Get all XML files in the schema directory $xmlFiles = \JFolder::files($this->xmlDirectory, '\.xml$'); if (empty($xmlFiles)) { return $xml; } foreach ($xmlFiles as $baseName) { // Remove any accidental whitespace $baseName = trim($baseName); // Get the full path to the file $fileName = $this->xmlDirectory . '/' . $baseName; $xml = $this->openAndVerify($fileName); if ($xml !== false) { return $xml; } } return null; } /** * Opens the schema XML file and return the SimpleXMLElement holding its information. If the file doesn't exist, it * is not a schema file or it doesn't match our database driver we return boolean false. * * @return false|SimpleXMLElement False if it's not a suitable XML schema file */ protected function openAndVerify($fileName) { $driverType = $this->db->name; // Make sure the file exists if (!@file_exists($fileName)) { return false; } // Make sure the file is a valid XML document try { $xml = new SimpleXMLElement($fileName, LIBXML_NONET, true); } catch (Exception $e) { $xml = null; return false; } // Make sure the file is an XML schema file if ($xml->getName() != 'schema') { $xml = null; return false; } if (!$xml->meta) { $xml = null; return false; } if (!$xml->meta->drivers) { $xml = null; return false; } /** @var SimpleXMLElement $drivers */ $drivers = $xml->meta->drivers; foreach ($drivers->children() as $driverTypeTag) { $thisDriverType = (string)$driverTypeTag; if ($thisDriverType == $driverType) { return $xml; } } // Some custom database drivers use a non-standard $name variable. Let try a relaxed match. foreach ($drivers->children() as $driverTypeTag) { $thisDriverType = (string)$driverTypeTag; if ( // e.g. $driverType = 'mysqlistupid', $thisDriverType = 'mysqli' => driver matched strpos($driverType, $thisDriverType) === 0 // e.g. $driverType = 'stupidmysqli', $thisDriverType = 'mysqli' => driver matched || (substr($driverType, -strlen($thisDriverType)) == $thisDriverType) ) { return $xml; } } return false; } /** * Checks if a condition is met * * @param string $table The table we're operating on * @param SimpleXMLElement $node The condition definition node * * @return bool */ protected function conditionMet($table, SimpleXMLElement $node) { if (empty(static::$allTables)) { static::$allTables = $this->db->getTableList(); } // Does the table exist? $tableNormal = $this->db->replacePrefix($table); $tableExists = in_array($tableNormal, static::$allTables); // Initialise $condition = false; // Get the condition's attributes $attributes = $node->attributes(); $type = $attributes->type ? $attributes->type : null; $value = $attributes->value ? (string) $attributes->value : null; switch ($type) { // Check if a table or column is missing case 'missing': $fieldName = (string)$value; if (empty($fieldName)) { $condition = !$tableExists; } else { try { $tableColumns = $this->db->getTableColumns($tableNormal, true); } catch (\Exception $e) { $tableColumns = array(); } $condition = !array_key_exists($fieldName, $tableColumns); } break; // Check if a column type matches the "coltype" attribute case 'type': try { $tableColumns = $this->db->getTableColumns($tableNormal, true); } catch (\Exception $e) { $tableColumns = array(); } $condition = false; if (array_key_exists($value, $tableColumns)) { $coltype = $attributes->coltype ? $attributes->coltype : null; if (!empty($coltype)) { $coltype = strtolower($coltype); $currentType = is_string($tableColumns[$value]) ? $tableColumns[$value] : strtolower($tableColumns[$value]->Type); $condition = ($coltype == $currentType); } } break; // Check if a (named) index exists on the table. Currently only supported on MySQL. case 'index': $indexName = (string) $value; $condition = true; if (!empty($indexName)) { $indexName = str_replace('#__', $this->db->getPrefix(), $indexName); $condition = $this->hasIndex($tableNormal, $indexName); } break; // Check if a table or column needs to be upgraded to utf8mb4 case 'utf8mb4upgrade': $condition = false; // Check if the driver and the database connection have UTF8MB4 support if (method_exists($this->db, 'hasUTF8mb4Support') && $this->db->hasUTF8mb4Support()) { $fieldName = (string)$value; if (empty($fieldName)) { $collation = $this->getTableCollation($tableNormal); } else { $collation = $this->getColumnCollation($tableNormal, $fieldName); } $parts = explode('_', $collation, 3); $encoding = empty($parts[0]) ? '' : strtolower($parts[0]); $condition = $encoding != 'utf8mb4'; } break; // Check if the result of a query matches our expectation case 'equals': $query = (string)$node; $this->db->setQuery($query); try { $result = $this->db->loadResult(); $condition = ($result == $value); } catch (Exception $e) { return false; } break; // Always returns true case 'true': return true; break; default: return false; break; } return $condition; } /** * Get the collation of a table. Uses an internal cache for efficiency. * * @param string $tableName The name of the table * * @return string The collation, e.g. "utf8_general_ci" */ private function getTableCollation($tableName) { static $cache = array(); $tableName = $this->db->replacePrefix($tableName); if (!isset($cache[$tableName])) { $cache[$tableName] = $this->realGetTableCollation($tableName); } return $cache[$tableName]; } /** * Get the collation of a table. This is the internal method used by getTableCollation. * * @param string $tableName The name of the table * * @return string The collation, e.g. "utf8_general_ci" */ private function realGetTableCollation($tableName) { $utf8Support = method_exists($this->db, 'hasUTFSupport') && $this->db->hasUTFSupport(); $utf8mb4Support = $utf8Support && method_exists($this->db, 'hasUTF8mb4Support') && $this->db->hasUTF8mb4Support(); $collation = $utf8mb4Support ? 'utf8mb4_unicode_ci' : ($utf8Support ? 'utf_general_ci' : 'latin1_swedish_ci'); $query = 'SHOW TABLE STATUS LIKE ' . $this->db->q($tableName); try { $row = $this->db->setQuery($query)->loadAssoc(); } catch (\Exception $e) { return $collation; } if (empty($row)) { return $collation; } if (!isset($row['Collation'])) { return $collation; } if (empty($row['Collation'])) { return $collation; } return $row['Collation']; } /** * Get the collation of a column. Uses an internal cache for efficiency. * * @param string $tableName The name of the table * @param string $columnName The name of the column * * @return string The collation, e.g. "utf8_general_ci" */ private function getColumnCollation($tableName, $columnName) { static $cache = array(); $tableName = $this->db->replacePrefix($tableName); $columnName = $this->db->replacePrefix($columnName); if (!isset($cache[$tableName])) { $cache[$tableName] = array(); } if (!isset($cache[$tableName][$columnName])) { $cache[$tableName][$columnName] = $this->realGetColumnCollation($tableName, $columnName); } return $cache[$tableName][$columnName]; } /** * Get the collation of a column. This is the internal method used by getColumnCollation. * * @param string $tableName The name of the table * @param string $columnName The name of the column * * @return string The collation, e.g. "utf8_general_ci" */ private function realGetColumnCollation($tableName, $columnName) { $collation = $this->getTableCollation($tableName); $query = 'SHOW FULL COLUMNS FROM ' . $this->db->qn($tableName) . ' LIKE ' . $this->db->q($columnName); try { $row = $this->db->setQuery($query)->loadAssoc(); } catch (\Exception $e) { return $collation; } if (empty($row)) { return $collation; } if (!isset($row['Collation'])) { return $collation; } if (empty($row['Collation'])) { return $collation; } return $row['Collation']; } /** * Automatically downgrade a CREATE TABLE or ALTER TABLE query from utf8mb4 (UTF-8 Multibyte) to plain utf8. * * We use our own method so we can be site it works even on Joomla! 3.4 or earlier, where UTF8MB4 support is not * implemented. * * @param string $query The query to convert * * @return string The converted query */ private function convertUtf8mb4QueryToUtf8($query) { // If it's not an ALTER TABLE or CREATE TABLE command there's nothing to convert $beginningOfQuery = substr($query, 0, 12); $beginningOfQuery = strtoupper($beginningOfQuery); if (!in_array($beginningOfQuery, array('ALTER TABLE ', 'CREATE TABLE'))) { return $query; } // Replace utf8mb4 with utf8 $from = array( 'utf8mb4_unicode_ci', 'utf8mb4_', 'utf8mb4', ); $to = array( 'utf8_general_ci', // Yeah, we convert utf8mb4_unicode_ci to utf8_general_ci per Joomla!'s conventions 'utf8_', 'utf8', ); return str_replace($from, $to, $query); } /** * Automatically upgrade a CREATE TABLE or ALTER TABLE query from plain utf8 to utf8mb4 (UTF-8 Multibyte). * * @param string $query The query to convert * * @return string The converted query */ private function convertUtf8QueryToUtf8mb4($query) { // If it's not an ALTER TABLE or CREATE TABLE command there's nothing to convert $beginningOfQuery = substr($query, 0, 12); $beginningOfQuery = strtoupper($beginningOfQuery); if (!in_array($beginningOfQuery, array('ALTER TABLE ', 'CREATE TABLE'))) { return $query; } // Replace utf8 with utf8mb4 $from = array( 'utf8_general_ci', 'utf8_', 'utf8', ); $to = array( 'utf8mb4_unicode_ci', // Yeah, we convert utf8_general_ci to utf8mb4_unicode_ci per Joomla!'s conventions 'utf8mb4_', 'utf8mb4', ); return str_replace($from, $to, $query); } /** * Analyzes a query. If it's a CREATE TABLE query the table is added to the $tables array. * * @param string $query The query to analyze * @param string $tables The array where the name of the detected table is added * * @return void */ private function extractTablesToConvert($query, &$tables) { // Normalize the whitespace of the query $query = trim($query); $query = str_replace(array("\r\n", "\r", "\n"), ' ', $query); while (strstr($query, ' ') !== false) { $query = str_replace(' ', ' ', $query); } // Is it a create table query? $queryStart = substr($query, 0, 12); $queryStart = strtoupper($queryStart); if ($queryStart != 'CREATE TABLE') { return; } // Remove the CREATE TABLE keyword. Also, If there's an IF NOT EXISTS clause remove it. $query = substr($query, 12); $query = str_ireplace('IF NOT EXISTS', '', $query); $query = trim($query); // Make sure there is a space between the table name and its definition, denoted by an open parenthesis $query = str_replace('(', ' (', $query); // Now we should have the name of the table, a space and the rest of the query. Extract the table name. $parts = explode(' ', $query, 2); $tableName = $parts[0]; /** * The table name may be quoted. Since UTF8MB4 is only supported in MySQL, the table name can only be * quoted with surrounding backticks. Therefore we can trim backquotes from the table name to unquote it! **/ $tableName = trim($tableName, '`'); // Finally, add the table name to $tables if it doesn't already exist. if (!in_array($tableName, $tables)) { $tables[] = $tableName; } } /** * Converts the collation of tables listed in $tablesToConvert to utf8mb4_unicode_ci * * @param array $tablesToConvert The list of tables to convert * * @return void */ private function convertTablesToUtf8mb4($tablesToConvert) { // Make sure the database driver REALLY has support for converting character sets if (!method_exists($this->db, 'getAlterTableCharacterSet')) { return; } asort($tablesToConvert); foreach ($tablesToConvert as $tableName) { $collation = $this->getTableCollation($tableName); $parts = explode('_', $collation, 3); $encoding = empty($parts[0]) ? '' : strtolower($parts[0]); if ($encoding != 'utf8mb4') { $queries = $this->db->getAlterTableCharacterSet($tableName); try { foreach ($queries as $query) { $this->db->setQuery($query)->execute(); } } catch (\Exception $e) { // We ignore failed conversions. Remember, you MUST change your indices MANUALLY. } } } } /** * Returns true if table $tableName has an index named $indexName or if it's impossible to retrieve index names for * the table (not enough privileges, not a MySQL database, ...) * * @param string $tableName The name of the table * @param string $indexName The name of the index * * @return bool */ private function hasIndex($tableName, $indexName) { static $isMySQL = null; static $cache = array(); if (is_null($isMySQL)) { $driverType = $this->db->name; $driverType = strtolower($driverType); $isMySQL = true; if ( !strpos($driverType, 'mysql') === 0 && !(substr($driverType, -5) == 'mysql') && !(substr($driverType, -6) == 'mysqli') ) { $isMySQL = false; } } // Not MySQL? Lie and return true. if (!$isMySQL) { return true; } if (!isset($cache[$tableName])) { $cache[$tableName] = array(); } if (!isset($cache[$tableName][$indexName])) { $cache[$tableName][$indexName] = true; try { $indices = array(); $query = 'SHOW INDEXES FROM ' . $this->db->qn($tableName); $indexDefinitions = $this->db->setQuery($query)->loadAssocList(); if (!empty($indexDefinitions) && is_array($indexDefinitions)) { foreach ($indexDefinitions as $def) { $indices[] = $def['Key_name']; } $indices = array_unique($indices); } $cache[$tableName][$indexName] = in_array($indexName, $indices); } catch (\Exception $e) { // Ignore errors } } return $cache[$tableName][$indexName]; } } Date/Date.php000064400000032470152325653700007025 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Date; use DateInterval; use DateTime; use DateTimeZone; use JDatabaseDriver; use JFactory; use JText; defined('_JEXEC') or die; /** * The Date class is a fork of Joomla's JDate. We had to fork that code in April 2017 when Joomla! 7.0 was released with * an untested change that completely broke date handling on PHP 7.0 and earlier versions. Since we can no longer trust * Joomla's core date and time handling we are providing our own, stable code. * * Date is a class that stores a date and provides logic to manipulate and render that date in a variety of formats. * * @method Date|bool add(DateInterval $interval) Adds an amount of days, months, years, hours, minutes and seconds to a JDate object. * @method Date|bool sub(DateInterval $interval) Subtracts an amount of days, months, years, hours, minutes and seconds from a JDate object. * @method Date|bool modify($modify) Alter the timestamp of this object by incre/decre-menting in a format accepted by strtotime(). * * @property-read string $daysinmonth t - Number of days in the given month. * @property-read string $dayofweek N - ISO-8601 numeric representation of the day of the week. * @property-read string $dayofyear z - The day of the year (starting from 0). * @property-read boolean $isleapyear L - Whether it's a leap year. * @property-read string $day d - Day of the month, 2 digits with leading zeros. * @property-read string $hour H - 24-hour format of an hour with leading zeros. * @property-read string $minute i - Minutes with leading zeros. * @property-read string $second s - Seconds with leading zeros. * @property-read string $microsecond u - Microseconds with leading zeros. * @property-read string $month m - Numeric representation of a month, with leading zeros. * @property-read string $ordinal S - English ordinal suffix for the day of the month, 2 characters. * @property-read string $week W - ISO-8601 week number of year, weeks starting on Monday. * @property-read string $year Y - A full numeric representation of a year, 4 digits. */ class Date extends DateTime { const DAY_ABBR = "\x021\x03"; const DAY_NAME = "\x022\x03"; const MONTH_ABBR = "\x023\x03"; const MONTH_NAME = "\x024\x03"; /** * The format string to be applied when using the __toString() magic method. * * @var string */ public static $format = 'Y-m-d H:i:s'; /** * Placeholder for a DateTimeZone object with GMT as the time zone. * * @var object */ protected static $gmt; /** * Placeholder for a DateTimeZone object with the default server * time zone as the time zone. * * @var object */ protected static $stz; /** * The DateTimeZone object for usage in rending dates as strings. * * @var DateTimeZone */ protected $tz; /** * Constructor. * * @param string $date String in a format accepted by strtotime(), defaults to "now". * @param mixed $tz Time zone to be used for the date. Might be a string or a DateTimeZone object. */ public function __construct($date = 'now', $tz = null) { // Create the base GMT and server time zone objects. if (empty(self::$gmt) || empty(self::$stz)) { self::$gmt = new DateTimeZone('GMT'); self::$stz = new DateTimeZone(@date_default_timezone_get()); } // If the time zone object is not set, attempt to build it. if (!($tz instanceof DateTimeZone)) { if ($tz === null) { $tz = self::$gmt; } elseif (is_string($tz)) { $tz = new DateTimeZone($tz); } } // On PHP 7.1 and later use an integer timestamp, without microseconds, to preserve backwards compatibility. // See http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.datetime-microseconds if ($date === 'now' && version_compare(PHP_VERSION, '7.1.0', '>=')) { $date = time(); } // If the date is numeric assume a unix timestamp and convert it. date_default_timezone_set('UTC'); $date = is_numeric($date) ? date('c', $date) : $date; // Call the DateTime constructor. parent::__construct($date, $tz); // Reset the timezone for 3rd party libraries/extension that does not use JDate date_default_timezone_set(self::$stz->getName()); // Set the timezone object for access later. $this->tz = $tz; } /** * Magic method to access properties of the date given by class to the format method. * * @param string $name The name of the property. * * @return mixed A value if the property name is valid, null otherwise. */ public function __get($name) { $value = null; switch ($name) { case 'daysinmonth': $value = $this->format('t', true); break; case 'dayofweek': $value = $this->format('N', true); break; case 'dayofyear': $value = $this->format('z', true); break; case 'isleapyear': $value = (boolean) $this->format('L', true); break; case 'day': $value = $this->format('d', true); break; case 'hour': $value = $this->format('H', true); break; case 'minute': $value = $this->format('i', true); break; case 'second': $value = $this->format('s', true); break; case 'month': $value = $this->format('m', true); break; case 'ordinal': $value = $this->format('S', true); break; case 'week': $value = $this->format('W', true); break; case 'year': $value = $this->format('Y', true); break; default: $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE ); } return $value; } /** * Magic method to render the date object in the format specified in the public * static member JDate::$format. * * @return string The date as a formatted string. */ public function __toString() { return (string) parent::format(self::$format); } /** * Proxy for new JDate(). * * @param string $date String in a format accepted by strtotime(), defaults to "now". * @param mixed $tz Time zone to be used for the date. * * @return Date */ public static function getInstance($date = 'now', $tz = null) { return new Date($date, $tz); } /** * Translates day of week number to a string. * * @param integer $day The numeric day of the week. * @param boolean $abbr Return the abbreviated day string? * * @return string The day of the week. */ public function dayToString($day, $abbr = false) { switch ($day) { case 0: default: return $abbr ? JText::_('SUN') : JText::_('SUNDAY'); case 1: return $abbr ? JText::_('MON') : JText::_('MONDAY'); case 2: return $abbr ? JText::_('TUE') : JText::_('TUESDAY'); case 3: return $abbr ? JText::_('WED') : JText::_('WEDNESDAY'); case 4: return $abbr ? JText::_('THU') : JText::_('THURSDAY'); case 5: return $abbr ? JText::_('FRI') : JText::_('FRIDAY'); case 6: return $abbr ? JText::_('SAT') : JText::_('SATURDAY'); } } /** * Gets the date as a formatted string in a local calendar. * * @param string $format The date format specification string (see {@link PHP_MANUAL#date}) * @param boolean $local True to return the date string in the local time zone, false to return it in GMT. * @param boolean $translate True to translate localised strings * * @return string The date string in the specified format format. */ public function calendar($format, $local = false, $translate = true) { return $this->format($format, $local, $translate); } /** * Gets the date as a formatted string. * * @param string $format The date format specification string (see {@link PHP_MANUAL#date}) * @param boolean $local True to return the date string in the local time zone, false to return it in GMT. * @param boolean $translate True to translate localised strings * * @return string The date string in the specified format format. */ public function format($format, $local = false, $translate = true) { if ($translate) { // Do string replacements for date format options that can be translated. $format = preg_replace('/(^|[^\\\])D/', "\\1" . self::DAY_ABBR, $format); $format = preg_replace('/(^|[^\\\])l/', "\\1" . self::DAY_NAME, $format); $format = preg_replace('/(^|[^\\\])M/', "\\1" . self::MONTH_ABBR, $format); $format = preg_replace('/(^|[^\\\])F/', "\\1" . self::MONTH_NAME, $format); } // If the returned time should not be local use GMT. if ($local == false && !empty(self::$gmt)) { parent::setTimezone(self::$gmt); } // Format the date. $return = parent::format($format); if ($translate) { // Manually modify the month and day strings in the formatted time. if (strpos($return, self::DAY_ABBR) !== false) { $return = str_replace(self::DAY_ABBR, $this->dayToString(parent::format('w'), true), $return); } if (strpos($return, self::DAY_NAME) !== false) { $return = str_replace(self::DAY_NAME, $this->dayToString(parent::format('w')), $return); } if (strpos($return, self::MONTH_ABBR) !== false) { $return = str_replace(self::MONTH_ABBR, $this->monthToString(parent::format('n'), true), $return); } if (strpos($return, self::MONTH_NAME) !== false) { $return = str_replace(self::MONTH_NAME, $this->monthToString(parent::format('n')), $return); } } if ($local == false && !empty($this->tz)) { parent::setTimezone($this->tz); } return $return; } /** * Get the time offset from GMT in hours or seconds. * * @param boolean $hours True to return the value in hours. * * @return float The time offset from GMT either in hours or in seconds. */ public function getOffsetFromGmt($hours = false) { return (float) $hours ? ($this->tz->getOffset($this) / 3600) : $this->tz->getOffset($this); } /** * Translates month number to a string. * * @param integer $month The numeric month of the year. * @param boolean $abbr If true, return the abbreviated month string * * @return string The month of the year. */ public function monthToString($month, $abbr = false) { switch ($month) { case 1: default: return $abbr ? JText::_('JANUARY_SHORT') : JText::_('JANUARY'); case 2: return $abbr ? JText::_('FEBRUARY_SHORT') : JText::_('FEBRUARY'); case 3: return $abbr ? JText::_('MARCH_SHORT') : JText::_('MARCH'); case 4: return $abbr ? JText::_('APRIL_SHORT') : JText::_('APRIL'); case 5: return $abbr ? JText::_('MAY_SHORT') : JText::_('MAY'); case 6: return $abbr ? JText::_('JUNE_SHORT') : JText::_('JUNE'); case 7: return $abbr ? JText::_('JULY_SHORT') : JText::_('JULY'); case 8: return $abbr ? JText::_('AUGUST_SHORT') : JText::_('AUGUST'); case 9: return $abbr ? JText::_('SEPTEMBER_SHORT') : JText::_('SEPTEMBER'); case 10: return $abbr ? JText::_('OCTOBER_SHORT') : JText::_('OCTOBER'); case 11: return $abbr ? JText::_('NOVEMBER_SHORT') : JText::_('NOVEMBER'); case 12: return $abbr ? JText::_('DECEMBER_SHORT') : JText::_('DECEMBER'); } } /** * Method to wrap the setTimezone() function and set the internal time zone object. * * @param DateTimeZone $tz The new DateTimeZone object. * * @return Date * * @note This method can't be type hinted due to a PHP bug: https://bugs.php.net/bug.php?id=61483 */ public function setTimezone($tz) { $this->tz = $tz; date_timezone_set($this, $tz); return $this; } /** * Gets the date as an ISO 8601 string. IETF RFC 3339 defines the ISO 8601 format * and it can be found at the IETF Web site. * * @param boolean $local True to return the date string in the local time zone, false to return it in GMT. * * @return string The date string in ISO 8601 format. * * @link http://www.ietf.org/rfc/rfc3339.txt */ public function toISO8601($local = false) { return $this->format(DateTime::RFC3339, $local, false); } /** * Gets the date as an SQL datetime string. * * @param boolean $local True to return the date string in the local time zone, false to return it in GMT. * @param JDatabaseDriver $db The database driver or null to use JFactory::getDbo() * * @return string The date string in SQL datetime format. * * @link http://dev.mysql.com/doc/refman/5.0/en/datetime.html */ public function toSql($local = false, JDatabaseDriver $db = null) { if ($db === null) { $db = JFactory::getDbo(); } return $this->format($db->getDateFormat(), $local, false); } /** * Gets the date as an RFC 822 string. IETF RFC 2822 supercedes RFC 822 and its definition * can be found at the IETF Web site. * * @param boolean $local True to return the date string in the local time zone, false to return it in GMT. * * @return string The date string in RFC 822 format. * * @link http://www.ietf.org/rfc/rfc2822.txt */ public function toRFC822($local = false) { return $this->format(DateTime::RFC2822, $local, false); } /** * Gets the date as UNIX time stamp. * * @return integer The date as a UNIX timestamp. */ public function toUnix() { return (int) parent::format('U'); } } Date/DateDecorator.php000064400000006450152325653700010667 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Date; use DateInterval; use DateTime; use JDatabaseDriver; defined('_JEXEC') or die; /** * This decorator will get any DateTime descendant and turn it into a FOF30\Date\Date compatible class. If the methods * specific to Date/JDate are available they will be used. Otherwise a new Date object will be spun from the information * in the decorated DateTime object and the results of a call to its method will be returned. */ class DateDecorator extends Date { /** * The decorated object * * @var DateTime */ protected $decorated = null; public function __construct($date = 'now', $tz = null) { if (is_object($date) && ($date instanceof DateTime)) { $this->decorated = $date; } else { $this->decorated = new Date($date, $tz); } $timestamp = $this->decorated->toISO8601(true); parent::__construct($timestamp); $this->setTimezone($this->decorated->getTimezone()); return; } /** * Magic method to access properties of the date given by class to the format method. * * @param string $name The name of the property. * * @return mixed A value if the property name is valid, null otherwise. */ public function __get($name) { return $this->decorated->$name; } public function __call($name, $arguments) { if (method_exists($this->decorated, $name)) { return call_user_func_array(array($this->decorated, $name), $arguments); } throw new \InvalidArgumentException("JDate object does not have a $name method"); } public function sub($interval) { // Note to self: ignore phpStorm; we must NOT use a typehint for $interval return $this->decorated->sub($interval); } public function add($interval) { // Note to self: ignore phpStorm; we must NOT use a typehint for $interval return $this->decorated->add($interval); } public function modify($modify) { return $this->decorated->modify($modify); } public function __toString() { return (string) $this->decorated; } public static function getInstance($date = 'now', $tz = null) { $coreObject = new Date($date, $tz); return new DateDecorator($coreObject); } public function dayToString($day, $abbr = false) { return $this->decorated->dayToString($day, $abbr); } public function calendar($format, $local = false, $translate = true) { return $this->decorated->calendar($format, $local, $translate); } public function format($format, $local = false, $translate = true) { return $this->decorated->format($format, $local, $translate); } public function getOffsetFromGmt($hours = false) { return $this->decorated->getOffsetFromGMT($hours); } public function monthToString($month, $abbr = false) { return $this->monthToString($month, $abbr); } public function setTimezone($tz) { return $this->decorated->setTimezone($tz); } public function toISO8601($local = false) { return $this->decorated->toISO8601($local); } public function toSql($local = false, JDatabaseDriver $db = null) { return $this->decorated->toSql($local, $db); } public function toRFC822($local = false) { return $this->decorated->toRFC822($local); } public function toUnix() { return $this->decorated->toUnix(); } } Dispatcher/Exception/AccessForbidden.php000064400000001220152325653700014322 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Dispatcher\Exception; use Exception; defined('_JEXEC') or die; /** * Exception thrown when the access to the requested resource is forbidden under the current execution context */ class AccessForbidden extends \RuntimeException { public function __construct( $message = "", $code = 403, Exception $previous = null ) { if (empty($message)) { $message = \JText::_('JLIB_APPLICATION_ERROR_ACCESS_FORBIDDEN'); } parent::__construct( $message, $code, $previous ); } } Dispatcher/Mixin/ViewAliases.php000064400000005150152325653700012654 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Dispatcher\Mixin; // Protect from unauthorized access use JFactory; use JUri; defined('_JEXEC') or die(); /** * Lets you create view aliases. When you access a view alias the real view is loaded instead. You can optionally have * an HTTPS 301 redirection for GET requests to URLs that use the view name alias. * * IMPORTANT: This is a mixin (or, as we call it in PHP, a trait). Traits require PHP 5.4 or later. If you opt to use * this trait your component will no longer work under PHP 5.3. * * Usage: * * • Override $viewNameAliases with your view names map. * • If you want to issue HTTP 301 for GET requests set $permanentAliasRedirectionOnGET to true. * • If you have an onBeforeDispatch method remember to alias and call this traits' onBeforeDispatch method at the top. * * Regarding the last point, if you've never used traits before, the code looks like this. Top of the class: * use ViewAliases { * onBeforeDispatch as onBeforeDispatchViewAliases; * } * and inside your custom onBeforeDispatch method, the first statement should be: * $this->onBeforeDispatchViewAliases(); * Simple! */ trait ViewAliases { /** * Maps view name aliases to actual views. The format is 'alias' => 'RealView'. * * @var array */ protected $viewNameAliases = []; /** * If set to true, any GET request to the alias view will result in an HTTP 301 permanent redirection to the real * view name. * * This does NOT apply to POST, PUT, DELETE etc URLs. When you submit form data you cannot have a redirection. The * browser will _typically_ not resend the submitted data. * * @var bool */ protected $permanentAliasRedirectionOnGET = false; /** * Transparently replaces old view names with their counterparts. * * If you are overriding this method in your component remember to alias it and call it from your overridden method. */ protected function onBeforeDispatch() { if (!array_key_exists($this->view, $this->viewNameAliases)) { return; } $this->view = $this->viewNameAliases[ $this->view ]; $this->container->input->set('view', $this->view); // Perform HTTP 301 Moved permanently redirection on GET requests if requested to do so if ($this->permanentAliasRedirectionOnGET && isset($_SERVER['REQUEST_METHOD']) && (strtoupper($_SERVER['REQUEST_METHOD']) == 'GET') ) { $url = JUri::getInstance(); $url->setVar('view', $this->view); $this->container->platform->redirect($url, 301); } } } Dispatcher/Dispatcher.php000064400000021162152325653700011443 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Dispatcher; use Exception; use FOF30\Container\Container; use FOF30\Controller\Controller; use FOF30\Dispatcher\Exception\AccessForbidden; use FOF30\TransparentAuthentication\TransparentAuthentication; defined('_JEXEC') or die; /** * A generic MVC dispatcher * * @property-read \FOF30\Input\Input $input The input object (magic __get returns the Input from the Container) */ class Dispatcher { /** @var string The name of the default view, in case none is specified */ public $defaultView = null; /** @var array Local cache of the dispatcher configuration */ protected $config = array(); /** @var Container The container we belong to */ protected $container = null; /** @var string The view which will be rendered by the dispatcher */ protected $view = null; /** @var string The layout for rendering the view */ protected $layout = null; /** @var Controller The controller which will be used */ protected $controller = null; /** @var bool Is this user transparently logged in? */ protected $isTransparentlyLoggedIn = false; /** * Public constructor * * The $config array can contain the following optional values: * defaultView string The view to render if none is specified in $input * * Do note that $config is passed to the Controller and through it to the Model and View. Please see these classes * for more information on the configuration variables they accept. * * @param \FOF30\Container\Container $container * @param array $config */ public function __construct(Container $container, array $config = array()) { $this->container = $container; $this->config = $config; $this->defaultView = $container->appConfig->get('dispatcher.defaultView', $this->defaultView); if (isset($config['defaultView'])) { $this->defaultView = $config['defaultView']; } // Get the default values for the view and layout names $this->view = $this->input->getCmd('view', null); $this->layout = $this->input->getCmd('layout', null); // Not redundant; you may pass an empty but non-null view which is invalid, so we need the fallback if (empty($this->view)) { $this->view = $this->defaultView; $this->container->input->set('view', $this->view); } } /** * Magic get method. Handles magic properties: * $this->input mapped to $this->container->input * * @param string $name The property to fetch * * @return mixed|null */ public function __get($name) { // Handle $this->input if ($name == 'input') { return $this->container->input; } // Property not found; raise error $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } /** * The main code of the Dispatcher. It spawns the necessary controller and * runs it. * * @return void * * @throws AccessForbidden When the access is forbidden */ public function dispatch() { // Load the translations for this component; $this->container->platform->loadTranslations($this->container->componentName); // Perform transparent authentication if ($this->container->platform->getUser()->guest) { $this->transparentAuthenticationLogin(); } // Get the event names (different for CLI) $onBeforeEventName = 'onBeforeDispatch'; $onAfterEventName = 'onAfterDispatch'; if ($this->container->platform->isCli()) { $onBeforeEventName = 'onBeforeDispatchCLI'; $onAfterEventName = 'onAfterDispatchCLI'; } try { $result = $this->triggerEvent($onBeforeEventName); $error = ''; } catch (\Exception $e) { $result = false; $error = $e->getMessage(); } if ($result === false) { if ($this->container->platform->isCli()) { $this->container->platform->setHeader('Status', '403 Forbidden', true); } $this->transparentAuthenticationLogout(); $this->container->platform->showErrorPage(new AccessForbidden); } // Get and execute the controller $view = $this->input->getCmd('view', $this->defaultView); $task = $this->input->getCmd('task', 'default'); if (empty($task)) { $task = 'default'; $this->input->set('task', $task); } try { $this->controller = $this->container->factory->controller($view, $this->config); $status = $this->controller->execute($task); } catch (Exception $e) { $this->container->platform->showErrorPage($e); // Redundant; just to make code sniffers happy return; } if ($status !== false) { try { $this->triggerEvent($onAfterEventName); } catch (\Exception $e) { $status = false; } } if (($status === false)) { if ($this->container->platform->isCli()) { $this->container->platform->setHeader('Status', '403 Forbidden', true); } $this->transparentAuthenticationLogout(); $this->container->platform->showErrorPage(new AccessForbidden); } $this->transparentAuthenticationLogout(); $this->controller->redirect(); } /** * Returns a reference to the Controller object currently in use by the dispatcher * * @return Controller */ public function &getController() { return $this->controller; } /** * Triggers an object-specific event. The event runs both locally –if a suitable method exists– and through the * Joomla! plugin system. A true/false return value is expected. The first false return cancels the event. * * EXAMPLE * Component: com_foobar, Object name: item, Event: onBeforeDispatch, Arguments: array(123, 456) * The event calls: * 1. $this->onBeforeDispatch(123, 456) * 2. Joomla! plugin event onComFoobarDispatcherBeforeDispatch($this, 123, 456) * * @param string $event The name of the event, typically named onPredicateVerb e.g. onBeforeKick * @param array $arguments The arguments to pass to the event handlers * * @return bool */ protected function triggerEvent($event, array $arguments = array()) { $result = true; // If there is an object method for this event, call it if (method_exists($this, $event)) { switch (count($arguments)) { case 0: $result = $this->{$event}(); break; case 1: $result = $this->{$event}($arguments[0]); break; case 2: $result = $this->{$event}($arguments[0], $arguments[1]); break; case 3: $result = $this->{$event}($arguments[0], $arguments[1], $arguments[2]); break; case 4: $result = $this->{$event}($arguments[0], $arguments[1], $arguments[2], $arguments[3]); break; case 5: $result = $this->{$event}($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4]); break; default: $result = call_user_func_array(array($this, $event), $arguments); break; } } if ($result === false) { return false; } // All other event handlers live outside this object, therefore they need to be passed a reference to this // objects as the first argument. array_unshift($arguments, $this); // If we have an "on" prefix for the event (e.g. onFooBar) remove it and stash it for later. $prefix = ''; if (substr($event, 0, 2) == 'on') { $prefix = 'on'; $event = substr($event, 2); } // Get the component/model prefix for the event $prefix .= 'Com' . ucfirst($this->container->bareComponentName) . 'Dispatcher'; // The event name will be something like onComFoobarItemsBeforeSomething $event = $prefix . $event; // Call the Joomla! plugins $results = $this->container->platform->runPlugins($event, $arguments); if (!empty($results)) { foreach ($results as $result) { if ($result === false) { return false; } } } return true; } /** * Handles the transparent authentication log in */ protected function transparentAuthenticationLogin() { /** @var TransparentAuthentication $transparentAuth */ $transparentAuth = $this->container->transparentAuth; $authInfo = $transparentAuth->getTransparentAuthenticationCredentials(); if (empty($authInfo)) { return; } $this->isTransparentlyLoggedIn = $this->container->platform->loginUser($authInfo); } /** * Handles the transparent authentication log out */ protected function transparentAuthenticationLogout() { if (!$this->isTransparentlyLoggedIn) { return; } /** @var TransparentAuthentication $transparentAuth */ $transparentAuth = $this->container->transparentAuth; if (!$transparentAuth->getLogoutOnExit()) { return; } $this->container->platform->logoutUser(); } } Download/Adapter/AbstractAdapter.php000064400000006477152325653700013476 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Download\Adapter; use FOF30\Download\DownloadInterface; use FOF30\Download\Exception\DownloadError; defined('_JEXEC') or die; abstract class AbstractAdapter implements DownloadInterface { /** * Load order priority * * @var int */ public $priority = 100; /** * Name of the adapter (identical to filename) * * @var string */ public $name = ''; /** * Is this adapter supported in the current execution environment? * * @var bool */ public $isSupported = false; /** * Does this adapter support chunked downloads? * * @var bool */ public $supportsChunkDownload = false; /** * Does this adapter support querying the remote file's size? * * @var bool */ public $supportsFileSize = false; /** * Does this download adapter support downloading files in chunks? * * @return boolean True if chunk download is supported */ public function supportsChunkDownload() { return $this->supportsChunkDownload; } /** * Does this download adapter support reading the size of a remote file? * * @return boolean True if remote file size determination is supported */ public function supportsFileSize() { return $this->supportsFileSize; } /** * Is this download class supported in the current server environment? * * @return boolean True if this server environment supports this download class */ public function isSupported() { return $this->isSupported; } /** * Get the priority of this adapter. If multiple download adapters are * supported on a site, the one with the highest priority will be * used. * * @return boolean */ public function getPriority() { return $this->priority; } /** * Returns the name of this download adapter in use * * @return string */ public function getName() { return $this->name; } /** * Download a part (or the whole) of a remote URL and return the downloaded * data. You are supposed to check the size of the returned data. If it's * smaller than what you expected you've reached end of file. If it's empty * you have tried reading past EOF. If it's larger than what you expected * the server doesn't support chunk downloads. * * If this class' supportsChunkDownload returns false you should assume * that the $from and $to parameters will be ignored. * * @param string $url The remote file's URL * @param integer $from Byte range to start downloading from. Use null for start of file. * @param integer $to Byte range to stop downloading. Use null to download the entire file ($from is ignored) * @param array $params Additional params that will be added before performing the download * * @return string The raw file data retrieved from the remote URL. * * @throws DownloadError A generic exception is thrown on error */ public function downloadAndReturn($url, $from = null, $to = null, array $params = array()) { return ''; } /** * Get the size of a remote file in bytes * * @param string $url The remote file's URL * * @return integer The file size, or -1 if the remote server doesn't support this feature */ public function getFileSize($url) { return -1; } } Download/Adapter/Curl.php000064400000015303152325653700011323 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Download\Adapter; use FOF30\Download\DownloadInterface; use FOF30\Download\Exception\DownloadError; use JText; defined('_JEXEC') or die; /** * A download adapter using the cURL PHP integration */ class Curl extends AbstractAdapter implements DownloadInterface { protected $headers = array(); public function __construct() { $this->priority = 110; $this->supportsFileSize = true; $this->supportsChunkDownload = true; $this->name = 'curl'; $this->isSupported = function_exists('curl_init') && function_exists('curl_exec') && function_exists('curl_close'); } /** * Download a part (or the whole) of a remote URL and return the downloaded * data. You are supposed to check the size of the returned data. If it's * smaller than what you expected you've reached end of file. If it's empty * you have tried reading past EOF. If it's larger than what you expected * the server doesn't support chunk downloads. * * If this class' supportsChunkDownload returns false you should assume * that the $from and $to parameters will be ignored. * * @param string $url The remote file's URL * @param integer $from Byte range to start downloading from. Use null for start of file. * @param integer $to Byte range to stop downloading. Use null to download the entire file ($from is ignored) * @param array $params Additional params that will be added before performing the download * * @return string The raw file data retrieved from the remote URL. * * @throws DownloadError A generic exception is thrown on error */ public function downloadAndReturn($url, $from = null, $to = null, array $params = array()) { $ch = curl_init(); if (empty($from)) { $from = 0; } if (empty($to)) { $to = 0; } if ($to < $from) { $temp = $to; $to = $from; $from = $temp; unset($temp); } curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_SSLVERSION, 0); curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/cacert.pem'); curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, 'reponseHeaderCallback')); if (!(empty($from) && empty($to))) { curl_setopt($ch, CURLOPT_RANGE, "$from-$to"); } if (!is_array($params)) { $params = array(); } $patched_accept_encoding = false; // Work around LiteSpeed sending compressed output under HTTP/2 when no encoding was requested // See https://github.com/joomla/joomla-cms/issues/21423#issuecomment-410941000 if (defined('CURLOPT_ACCEPT_ENCODING')) { if (!array_key_exists(CURLOPT_ACCEPT_ENCODING, $params)) { $params[CURLOPT_ACCEPT_ENCODING] = 'identity'; } $patched_accept_encoding = true; } if (!empty($params)) { foreach ($params as $k => $v) { // I couldn't patch the accept encoding header (missing constant), so I'll check if we manually set it if (!$patched_accept_encoding && $k == CURLOPT_HTTPHEADER) { foreach ($v as $custom_header) { // Ok, we explicitly set the Accept-Encoding header, so we consider it patched if (stripos($custom_header, 'Accept-Encoding') !== false) { $patched_accept_encoding = true; } } } @curl_setopt($ch, $k, $v); } } // Accept encoding wasn't patched, let's manually do that if (!$patched_accept_encoding) { @curl_setopt($ch, CURLOPT_HTTPHEADER, array('Accept-Encoding: identity')); $patched_accept_encoding = true; } $result = curl_exec($ch); $errno = curl_errno($ch); $errmsg = curl_error($ch); $error = ''; $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($result === false) { $error = JText::sprintf('LIB_FOF_DOWNLOAD_ERR_CURL_ERROR', $errno, $errmsg); } elseif (($http_status >= 300) && ($http_status <= 399) && isset($this->headers['location']) && !empty($this->headers['location'])) { return $this->downloadAndReturn($this->headers['location'], $from, $to, $params); } elseif ($http_status > 399) { $result = false; $errno = $http_status; $error = JText::sprintf('LIB_FOF_DOWNLOAD_ERR_HTTPERROR', $http_status); } curl_close($ch); if ($result === false) { throw new DownloadError($error, $errno); } else { return $result; } } /** * Get the size of a remote file in bytes * * @param string $url The remote file's URL * * @return integer The file size, or -1 if the remote server doesn't support this feature */ public function getFileSize($url) { $result = -1; $ch = curl_init(); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); curl_setopt($ch, CURLOPT_SSLVERSION, 0); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_NOBODY, true ); curl_setopt($ch, CURLOPT_HEADER, true ); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true ); @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true ); curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . '/cacert.pem'); $data = curl_exec($ch); curl_close($ch); if ($data) { $content_length = "unknown"; $status = "unknown"; $redirection = null; if (preg_match( "/^HTTP\/1\.[01] (\d\d\d)/i", $data, $matches)) { $status = (int)$matches[1]; } if (preg_match( "/Content-Length: (\d+)/i", $data, $matches)) { $content_length = (int)$matches[1]; } if (preg_match( "/Location: (.*)/i", $data, $matches)) { $redirection = (int)$matches[1]; } if( $status == 200 || ($status > 300 && $status <= 308) ) { $result = $content_length; } if (($status > 300) && ($status <= 308)) { if (!empty($redirection)) { return $this->getFileSize($redirection); } return -1; } } return $result; } /** * Handles the HTTP headers returned by cURL * * @param resource $ch cURL resource handle (unused) * @param string $data Each header line, as returned by the server * * @return int The length of the $data string */ protected function reponseHeaderCallback(&$ch, &$data) { $strlen = strlen($data); if (($strlen) <= 2) { return $strlen; } if (substr($data, 0, 4) == 'HTTP') { return $strlen; } if (strpos($data, ':') === false) { return $strlen; } list($header, $value) = explode(': ', trim($data), 2); $this->headers[strtolower($header)] = $value; return $strlen; } } Download/Adapter/Fopen.php000064400000007616152325653700011475 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Download\Adapter; use FOF30\Download\DownloadInterface; use FOF30\Download\Exception\DownloadError; use JText; defined('_JEXEC') or die; /** * A download adapter using URL fopen() wrappers */ class Fopen extends AbstractAdapter implements DownloadInterface { public function __construct() { $this->priority = 100; $this->supportsFileSize = false; $this->supportsChunkDownload = true; $this->name = 'fopen'; // If we are not allowed to use ini_get, we assume that URL fopen is disabled if (!function_exists('ini_get')) { $this->isSupported = false; } else { $this->isSupported = ini_get('allow_url_fopen'); } } /** * Download a part (or the whole) of a remote URL and return the downloaded * data. You are supposed to check the size of the returned data. If it's * smaller than what you expected you've reached end of file. If it's empty * you have tried reading past EOF. If it's larger than what you expected * the server doesn't support chunk downloads. * * If this class' supportsChunkDownload returns false you should assume * that the $from and $to parameters will be ignored. * * @param string $url The remote file's URL * @param integer $from Byte range to start downloading from. Use null for start of file. * @param integer $to Byte range to stop downloading. Use null to download the entire file ($from is ignored) * @param array $params Additional params that will be added before performing the download * * @return string The raw file data retrieved from the remote URL. * * @throws DownloadError A generic exception is thrown on error */ public function downloadAndReturn($url, $from = null, $to = null, array $params = array()) { if (empty($from)) { $from = 0; } if (empty($to)) { $to = 0; } if ($to < $from) { $temp = $to; $to = $from; $from = $temp; unset($temp); } if (!(empty($from) && empty($to))) { $options = array( 'http' => array( 'method' => 'GET', 'header' => "Range: bytes=$from-$to\r\n" ), 'ssl' => array( 'verify_peer' => true, 'cafile' => __DIR__ . '/cacert.pem', 'verify_depth' => 5, ) ); $options = array_merge($options, $params); $context = stream_context_create($options); $result = @file_get_contents($url, false, $context, $from - $to + 1); } else { $options = array( 'http' => array( 'method' => 'GET', ), 'ssl' => array( 'verify_peer' => true, 'cafile' => __DIR__ . '/cacert.pem', 'verify_depth' => 5, ) ); $options = array_merge($options, $params); $context = stream_context_create($options); $result = @file_get_contents($url, false, $context); } global $http_response_header_test; if (!isset($http_response_header) && empty($http_response_header_test)) { $error = JText::_('LIB_FOF_DOWNLOAD_ERR_FOPEN_ERROR'); throw new DownloadError($error, 404); } else { // Used for testing if (!isset($http_response_header) && !empty($http_response_header_test)) { $http_response_header = $http_response_header_test; } $http_code = 200; $nLines = count($http_response_header); for ($i = $nLines - 1; $i >= 0; $i--) { $line = $http_response_header[$i]; if (strncasecmp("HTTP", $line, 4) == 0) { $response = explode(' ', $line); $http_code = $response[1]; break; } } if ($http_code >= 299) { $error = JText::sprintf('LIB_FOF_DOWNLOAD_ERR_HTTPERROR', $http_code); throw new DownloadError($error, $http_code); } } if ($result === false) { $error = JText::sprintf('LIB_FOF_DOWNLOAD_ERR_FOPEN_ERROR'); throw new DownloadError($error, 1); } else { return $result; } } } Download/Adapter/cacert.pem000064400001110611152325653700011650 0ustar00## ## Bundle of CA Root Certificates ## ## Certificate data from CentOS as of Oct 3 2015 ## ## This is a bundle of X.509 certificates of public Certificate Authorities ## (CA). These were automatically extracted from CentOS /etc/pki/tls/certs/ca-bundle.crt ## ## It contains the certificates in PEM format and therefore ## can be directly used with curl / libcurl / php_curl, or with ## an Apache+mod_ssl webserver for SSL client authentication. ## Just configure this file as the SSLCACertificateFile. ## -----BEGIN CERTIFICATE----- MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4 04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9 3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3 dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3 DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91 yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG 7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ qdq5snUb9kLy78fyGPmJvKP/iiMucEc= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG 9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1 MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y 7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh 1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5 fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i +DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+ gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/ k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3 MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5 WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G CSqGSIb3DQEBAgUAA4GBALtMEivPLCYATxQT3ab7/AoRhIzzKBxnki98tsX63/Do lbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59AhWM1pF+NEHJwZRDmJXNyc AA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2OmufTqj/ZA1k -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68 DzFc6PLZ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn jBJ7xUS0rg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5 MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4 pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0 13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY oJ2daZH9 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp 1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8 9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE 38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG 9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+ TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0 LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG 9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9 WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0 IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG 9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs 2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4 nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO 8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2 6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4 wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3 ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4 E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u 7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te 2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC /Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1 GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ +mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1 CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c 2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/ bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1 MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/ I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3 wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5 BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0 MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN 95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd 2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1 BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3 DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92 9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0 Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc 58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/ o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv 8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+ WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN /Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC +Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X 7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz 43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290 MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9 uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0 WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0 Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV 6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH 1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF 62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6 IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/ iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh 4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3 b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1 MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G 87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i 2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1 0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3 P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no xqE= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6 MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg /9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2 PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/ Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+ f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch 6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3 7CAFYd4= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9 9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU 1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+ bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV 5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h 2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq 299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3 LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd 7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw ++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt 398znM/jra6O1I7mT1GvFpLgXPYHDw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7 HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs 6GAqm4VKQPNriiTsBhYscw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe 3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4 YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2 G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3 smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996 CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk 3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz 6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0 5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0 aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW 1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7 kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/ HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32 pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+ xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0 aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0 aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8 7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK SnQ2+Q== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5 WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8 9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9 Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5 Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAx MDQwNjEwNDkxM1oXDTIxMDQwNjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNV BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMSBDQTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H887dF+2rDNbS82rDTG 29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9EJUk oVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk 3w0LBUXl0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBL qdReLjVQCfOAl/QMF6452F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIIN nvmLVz5MxxftLItyM19yejhW1ebZrgUaHXVFsculJRwSVzb9IjcCAwEAAaMzMDEw DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZTiFIwCwYDVR0PBAQDAgEG MA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE928Jj2VuX ZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0H DjxVyhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VO TzF2nBBhjrZTOqMRvq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2Uv kVrCqIexVmiUefkl98HVrhq4uz2PqYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4w zMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9ZIRlXvVWa -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt 5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s 3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu 8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/ 3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6 Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2 ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71 9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA 7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k /rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6 u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy 7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6 E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK 4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv 2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3 mfnGV/TJVTl4uix5yaaIK/QI -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9 hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM 1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws 6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50 aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u 7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0 xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn 0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0 dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM //bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t 3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCB lTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAbBgNVBAMTFFVUTi1VU0VSRmlyc3Qt T2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAzNlowgZUxCzAJBgNV BAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkxHjAc BgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3 dy51c2VydHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicP HxzfOpuCaDDASmEd8S8O+r5596Uj71VRloTN2+O5bj4x2AogZ8f02b+U60cEPgLO KqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQw5ujm9M89RKZd7G3CeBo 5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vulBe3/IW+ pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehb kkj7RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUC AwEAAaOBrzCBrDALBgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E FgQU2u1kdBScFDyr3ZmpvVsoTYs8ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDov L2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmlyc3QtT2JqZWN0LmNybDApBgNV HSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQwDQYJKoZIhvcN AQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXB mMiKVl0+7kNOPmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU 4U3GDZlDAQ0Slox4nb9QorFEqmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK5 81OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCGhU3IfdeLA/5u1fedFqySLKAj5ZyR Uh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq 7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3 0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p 26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi 1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0 eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu tGWaIZDgqtCYvDi1czyL+Nw= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9 MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0 Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795 B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/ AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUx ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQD EzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVneXpvaSAoQ2xhc3MgUUEpIFRhbnVz aXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0bG9jay5odTAeFw0w MzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTERMA8G A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5l dExvY2sgTWlub3NpdGV0dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZh bnlraWFkbzEeMBwGCSqGSIb3DQEJARYPaW5mb0BuZXRsb2NrLmh1MIIBIjANBgkq hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRVCacbvWy5FPSKAtt2/Goq eKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e8ia6AFQe r7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO5 3Lhbm+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWd vLrqOU+L73Sa58XQ0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0l mT+1fMptsK6ZmfoIYOcZwvK9UdPM0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4IC wDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwggJ1Bglg hkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2YW55IGEgTmV0 TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQg ZWxla3Ryb25pa3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywg dmFsYW1pbnQgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6 b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwgYXogQWx0YWxhbm9zIFN6ZXJ6b2Rl c2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kgZWxqYXJhcyBtZWd0 ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczovL3d3 dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0Bu ZXRsb2NrLm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBh bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRo ZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMgYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3 Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0IGluZm9AbmV0bG9jay5u ZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3DQEBBQUA A4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQ MznNwNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+ NFAwLvt/MpqNPfMgW/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCR VCHnpgu0mfVRQdzNo0ci2ccBgcTcR08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY 83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR5qq5aKrN9p2QdRLqOBrKROi3 macqaJVmlaut74nLYKkGEsaUR+ko -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0 dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0 N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi 3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8 WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4 QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0 YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3 Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6 ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1 YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP 0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK 8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUx ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQD EylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05 OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYDVQQGEwJIVTERMA8G A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5l dExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqG SIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK gZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvc Q7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8E BAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1G SUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFu b3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBh bGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExv Y2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGln aXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0 IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGph biBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJo ZXRvIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBP UlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmlj YXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBo dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNA bmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06 sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS NitjrFgBazMpUIaD8QFI -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0 b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC 2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0 YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0 aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4 Fp1hBWeAyNDYpQcCNJgEjTME1A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3 dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6 38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4 qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0 eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ O+7ETPTsJ3xCwnR8gooJybQDJbw= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3 MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+ YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h /t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5 IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf ReYNnyicsbkqWletNw+vHX/bvZ8= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3 DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf 8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN +lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0 X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA 1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0 YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3 L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9 MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w +2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B 26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0 Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ 9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8 jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1 ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y 5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ 4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+ wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4 VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/ AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe +o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97 nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4 gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm +9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep +OkuE6N36B9K -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/ 0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47 4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2 VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA 7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH 7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UE AwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00x CzAJBgNVBAYTAkVTMB4XDTA4MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEW MBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZF RElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC AgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHkWLn7 09gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7 XBZXehuDYAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5P Grjm6gSSrj0RuVFCPYewMYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAK t0SdE3QrwqXrIhWYENiLxQSfHY9g5QYbm8+5eaA9oiM/Qj9r+hwDezCNzmzAv+Yb X79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbkHQl/Sog4P75n/TSW9R28 MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTTxKJxqvQU fecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI 2Sf23EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyH K9caUPgn6C9D4zq92Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEae ZAwUswdbxcJzbPEHXEUkFDWug/FqTYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAP BgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz4SsrSbbXc6GqlPUB53NlTKxQ MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU9QHnc2VMrFAw RAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWIm fQwng4/F9tqgaHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3 gvoFNTPhNahXwOf9jU8/kzJPeGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKe I6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1PwkzQSulgUV1qzOMPPKC8W64iLgpq0i 5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1ThCojz2GuHURwCRi ipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oIKiMn MCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZ o5NjEFIqnxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6 zqylfDJKZ0DcMDQj3dcEI2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacN GHk0vFQYXlPKNFHtRQrmjseCNj6nOGOpMCwXEGCSn1WHElkQwg9naRHMTh5+Spqt r0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3otkYNbn5XOmeUwssfnHdK Z05phkOTOPu220+DkdRgfks+KzgHVZhepA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsx CzAJBgNVBAYTAkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRp ZmljYWNpw7NuIERpZ2l0YWwgLSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwa QUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4wHhcNMDYxMTI3MjA0NjI5WhcNMzAw NDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+U29jaWVkYWQgQ2Ft ZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJhIFMu QS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkq hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeG qentLhM0R7LQcNzJPNCNyu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzL fDe3fezTf3MZsGqy2IiKLUV0qPezuMDU2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQ Y5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU34ojC2I+GdV75LaeHM/J4 Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP2yYe68yQ 54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+b MMCm8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48j ilSH5L887uvDdUhfHjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++Ej YfDIJss2yKHzMI+ko6Kh3VOz3vCaMh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/zt A/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK5lw1omdMEWux+IBkAC1vImHF rEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1bczwmPS9KvqfJ pxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCB lTCBkgYEVR0gADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFy YS5jb20vZHBjLzBaBggrBgEFBQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW50 7WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2UgcHVlZGVuIGVuY29udHJhciBlbiBs YSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEfAygPU3zmpFmps4p6 xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuXEpBc unvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/ Jre7Ir5v/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dp ezy4ydV/NgIlqmjCMRW3MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42 gzmRkBDI8ck1fj+404HGIGQatlDCIaR43NAvO2STdPCWkPHv+wlaNECW8DYSwaN0 jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wkeZBWN7PGKX6jD/EpOe9+ XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f/RWmnkJD W2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/ RL5hRqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35r MDOhYil/SrnhLecUIw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxk BYn8eNZcLCZDqQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290 IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1 ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX 4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9 KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/ gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ 51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7 jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70 jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1 yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/ nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp 6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48 x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ +jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5 HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7 70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S 5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2 KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B 8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc 0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8 GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e KeC2uAloGRwYQw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D 0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9 ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEc MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRp b25DQTAeFw0wNzEyMTIxNTAwMDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYT AkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zlcm5tZW50MRYwFAYDVQQLEw1BcHBs aWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp23gdE6H j6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4fl+K f5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55 IrmTwcrNwVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cw FO5cjFW6WY2H/CPek9AEjP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDiht QWEjdnjDuGWk81quzMKq2edY3rZ+nYVunyoKb58DKTCXKB28t89UKU5RMfkntigm /qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRUWssmP3HMlEYNllPqa0jQ k/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNVBAYTAkpQ MRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOC seODvOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD ggEBADlqRHZ3ODrso2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJ hyzjVOGjprIIC8CFqMjSnHH2HZ9g/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+ eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYDio+nEhEMy/0/ecGc/WLuo89U DNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmWdupwX3kSa+Sj B1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL rosot4LKGAfmt1t06SAZf7IbiVQ= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+ SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ 4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3 DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJB VDFIMEYGA1UECgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBp bSBlbGVrdHIuIERhdGVudmVya2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5R dWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5RdWFsLTAzMB4XDTA1MDgxNzIyMDAw MFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgwRgYDVQQKDD9BLVRy dXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0ZW52 ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMM EEEtVHJ1c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQCtPWFuA/OQO8BBC4SAzewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUj lUC5B3ilJfYKvUWG6Nm9wASOhURh73+nyfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZ znF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPESU7l0+m0iKsMrmKS1GWH 2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4iHQF63n1 k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs 2e3Vcuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYD VR0OBAoECERqlWdVeRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC AQEAVdRU0VlIXLOThaq/Yy/kgM40ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fG KOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmrsQd7TZjTXLDR8KdCoLXEjq/+ 8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZdJXDRZslo+S4R FGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmE DNuxUCAKGkq6ahq97BvIxYSazQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9 thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF 6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF 661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9 am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1 ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481 PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS 3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF 3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg Q2xhc3MgMiBDQSAxMB4XDTA2MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzEL MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD VQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7McXA0 ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLX l18xoS830r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVB HfCuuCkslFJgNJQ72uA40Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B 5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/RuFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3 WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNCMEAwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0PAQH/BAQD AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLP gcIV1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+ DKhQ7SLHrQVMdvvt7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKu BctN518fV4bVIJwo+28TOPX2EZL2fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHs h7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5wwDX3OaJdZtB7WZ+oRxKaJyOk LY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr 6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91 1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN 9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h 9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo +fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7 KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2 DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7 5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h 3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg Q2xhc3MgMyBDQSAxMB4XDTA1MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzEL MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD VQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP ADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKxifZg isRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//z NIqeKNc0n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI +MkcVyzwPX6UvCWThOiaAJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2R hzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+ mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNCMEAwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0PAQH/BAQD AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFP Bdy7pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27s EzNxZy5p+qksP2bAEllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2 mSlf56oBzKwzqBwKu5HEA6BvtjT5htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yC e/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQjel/wroQk5PMr+4okoyeYZdow dXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9 tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX 0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c /3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D 34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3 AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2 HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv 033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41 3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq 4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzET MBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UE AxMIQ0EgRGlzaWcwHhcNMDYwMzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQsw CQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcg YS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgmGErE Nx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnX mjxUizkDPw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYD XcDtab86wYqg6I7ZuUUohwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhW S8+2rT+MitcE5eN4TPWGqvWP+j1scaMtymfraHtuM6kMgiioTGohQBUgDCZbg8Kp FhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8wgfwwDwYDVR0TAQH/BAUw AwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0PAQH/BAQD AgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cu ZGlzaWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5z ay9jYS9jcmwvY2FfZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2sv Y2EvY3JsL2NhX2Rpc2lnLmNybDAaBgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEw DQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59tWDYcPQuBDRIrRhCA/ec8J9B6 yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3mkkp7M5+cTxq EEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/ CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeB EicTXxChds6KezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFN PGO+I++MzVpQuGhU+QqZMxEA4Z7CRneC9VkGjCFMhwnN5ag= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAMMDmu5QkG4oMA0GCSqGSIb3DQEBBQUAMFIxCzAJBgNV BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIxMB4XDTEyMDcxOTA5MDY1NloXDTQy MDcxOTA5MDY1NlowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjEw ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqw3j33Jijp1pedxiy3QRk D2P9m5YJgNXoqqXinCaUOuiZc4yd39ffg/N4T0Dhf9Kn0uXKE5Pn7cZ3Xza1lK/o OI7bm+V8u8yN63Vz4STN5qctGS7Y1oprFOsIYgrY3LMATcMjfF9DCCMyEtztDK3A fQ+lekLZWnDZv6fXARz2m6uOt0qGeKAeVjGu74IKgEH3G8muqzIm1Cxr7X1r5OJe IgpFy4QxTaz+29FHuvlglzmxZcfe+5nkCiKxLU3lSCZpq+Kq8/v8kiky6bM+TR8n oc2OuRf7JT7JbvN32g0S9l3HuzYQ1VTW8+DiR0jm3hTaYVKvJrT1cU/J19IG32PK /yHoWQbgCNWEFVP3Q+V8xaCJmGtzxmjOZd69fwX3se72V6FglcXM6pM6vpmumwKj rckWtc7dXpl4fho5frLABaTAgqWjR56M6ly2vGfb5ipN0gTco65F97yLnByn1tUD 3AjLLhbKXEAz6GfDLuemROoRRRw1ZS0eRWEkG4IupZ0zXWX4Qfkuy5Q/H6MMMSRE 7cderVC6xkGbrPAXZcD4XW9boAo0PO7X6oifmPmvTiT6l7Jkdtqr9O3jw2Dv1fkC yC2fg69naQanMVXVz0tv/wQFx1isXxYb5dKj6zHbHzMVTdDypVP1y+E9Tmgt2BLd qvLmTZtJ5cUoobqwWsagtQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud DwEB/wQEAwIBBjAdBgNVHQ4EFgQUiQq0OJMa5qvum5EY+fU8PjXQ04IwDQYJKoZI hvcNAQEFBQADggIBADKL9p1Kyb4U5YysOMo6CdQbzoaz3evUuii+Eq5FLAR0rBNR xVgYZk2C2tXck8An4b58n1KeElb21Zyp9HWc+jcSjxyT7Ff+Bw+r1RL3D65hXlaA SfX8MPWbTx9BLxyE04nH4toCdu0Jz2zBuByDHBb6lM19oMgY0sidbvW9adRtPTXo HqJPYNcHKfyyo6SdbhWSVhlMCrDpfNIZTUJG7L399ldb3Zh+pE3McgODWF3vkzpB emOqfDqo9ayk0d2iLbYq/J8BjuIQscTK5GfbVSUZP/3oNn6z4eGBrxEWi1CXYBmC AMBrTXO40RMHPuq2MU/wQppt4hF05ZSsjYSVPCGvxdpHyN85YmLLW1AL14FABZyb 7bq2ix4Eb5YgOe2kfSnbSM6C3NQCjR0EMVrHS/BsYVLXtFHCgWzN4funodKSds+x DzdYpPJScWc/DIh4gInByLUfkmO+p3qKViwaqKactV2zY9ATIKHrkWzQjX2v3wvk F7mGnjixlAxYjOBVqjtjbZqJYLhkKpLGN/R+Q0O3c+gB53+XD9fyexn9GtePyfqF a3qdnom2piiZk4hA9z7NUaPK6u95RyG1/jLix8NRb76AdPCkwzryT+lf3xkK8jsT Q6wxpLPn6/wY1gGp8yqPNg7rtLG8t0zJa7+h89n07eLw4+1knj0vllJPgFOL -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912 H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1 rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka +elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3 gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3 DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4 QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q 130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2 JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG 9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjET MBEGA1UEChMKQ2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAk BgNVBAMMHUNlcnRpbm9taXMgLSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4 Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkGA1UEBhMCRlIxEzARBgNVBAoTCkNl cnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYwJAYDVQQDDB1DZXJ0 aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQADggIP ADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jY F1AMnmHawE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N 8y4oH3DfVS9O7cdxbwlyLu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWe rP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K /OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92NjMD2AR5vpTESOH2VwnHu 7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9qc1pkIuVC 28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6 lSTClrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1E nn1So2+WLhl+HPNbxxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB 0iSVL1N6aaLwD4ZFjliCK0wi1F6g530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql09 5gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna4NH4+ej9Uji29YnfAgMBAAGj WzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBQN jLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9s ov3/4gbIOZ/xWqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZM OH8oMDX/nyNTt7buFHAAQCvaR6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q 619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40nJ+U8/aGH88bc62UeYdocMMzpXDn 2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1BCxMjidPJC+iKunqj o3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjvJL1v nxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG 5ERQL1TEqkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWq pdEdnV1j6CTmNhTih60bWfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZb dsLLO7XSAPCjDuGtbkD326C00EauFddEwk01+dIL8hf2rGbVJLJP0RyZwG71fet0 BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/vgt2Fl43N+bYdJeimUV5 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9 MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0 HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4 QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/ AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8 yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7 l7+ijrRU -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do 0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ 44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN 9u6wWk5JRFRYX0KD -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3 WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8 J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI 03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03 sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5 /ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp 7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19 xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN 5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe /v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ 5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9 28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR 5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s +12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5 Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1 +HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF 5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1 glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2 pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ d0jQ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID9zCCAt+gAwIBAgIESJ8AATANBgkqhkiG9w0BAQUFADCBijELMAkGA1UEBhMC Q04xMjAwBgNVBAoMKUNoaW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24g Q2VudGVyMUcwRQYDVQQDDD5DaGluYSBJbnRlcm5ldCBOZXR3b3JrIEluZm9ybWF0 aW9uIENlbnRlciBFViBDZXJ0aWZpY2F0ZXMgUm9vdDAeFw0xMDA4MzEwNzExMjVa Fw0zMDA4MzEwNzExMjVaMIGKMQswCQYDVQQGEwJDTjEyMDAGA1UECgwpQ2hpbmEg SW50ZXJuZXQgTmV0d29yayBJbmZvcm1hdGlvbiBDZW50ZXIxRzBFBgNVBAMMPkNo aW5hIEludGVybmV0IE5ldHdvcmsgSW5mb3JtYXRpb24gQ2VudGVyIEVWIENlcnRp ZmljYXRlcyBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm35z 7r07eKpkQ0H1UN+U8i6yjUqORlTSIRLIOTJCBumD1Z9S7eVnAztUwYyZmczpwA// DdmEEbK40ctb3B75aDFk4Zv6dOtouSCV98YPjUesWgbdYavi7NifFy2cyjw1l1Vx zUOFsUcW9SxTgHbP0wBkvUCZ3czY28Sf1hNfQYOL+Q2HklY0bBoQCxfVWhyXWIQ8 hBouXJE0bhlffxdpxWXvayHG1VA6v2G5BY3vbzQ6sm8UY78WO5upKv23KzhmBsUs 4qpnHkWnjQRmQvaPK++IIGmPMowUc9orhpFjIpryp9vOiYurXccUwVswah+xt54u gQEC7c+WXmPbqOY4twIDAQABo2MwYTAfBgNVHSMEGDAWgBR8cks5x8DbYqVPm6oY NJKiyoOCWTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E FgQUfHJLOcfA22KlT5uqGDSSosqDglkwDQYJKoZIhvcNAQEFBQADggEBACrDx0M3 j92tpLIM7twUbY8opJhJywyA6vPtI2Z1fcXTIWd50XPFtQO3WKwMVC/GVhMPMdoG 52U7HW8228gd+f2ABsqjPWYWqJ1MFn3AlUa1UeTiH9fqBk1jjZaM7+czV0I664zB echNdn3e9rG3geCg+aF4RhcaVpjwTj2rHO3sOdwHSPdj/gauwqRcalsyiMXHM4Ws ZkJHwlgkmeHlPuV1LI5D1l08eB6olYIpUNHRFrrvwb562bTYzB5MRuF3sTGrvSrI zo9uoV1/A3U05K2JRVRevq4opbs/eHnrc7MKDf2+yfdWrPa37S+bISnHOLaVxATy wy39FCqQmbkHzJ8= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2 MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6 dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO 76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj 2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0 aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3 UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI 2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8 Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp +2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+ DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW /zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/ RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4 zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB ZQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5 MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR 6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC 9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV /erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z +pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB /wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM 4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV 2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl 0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB NVOFBkpdn627G190 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0 MRMwEQYDVQQDEwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQG EwJJTDAeFw0wNDAzMjQxMTMyMThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMT CkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNpZ24xCzAJBgNVBAYTAklMMIIBIjAN BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49qROR+WCf4C9DklBKK 8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTyP2Q2 98CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb 2CEJKHxNGGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxC ejVb7Us6eva1jsz/D3zkYDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7Kpi Xd3DTKaCQeQzC6zJMw9kglcq/QytNuEMrkvF7zuZ2SOzW120V+x0cAwqTwIDAQAB o4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Zl ZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0PAQH/BAQD AgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRL AZs+VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWd foPPbrxHbvUanlR2QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0M cXS6hMTXcpuEfDhOZAYnKuGntewImbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq 8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb/627HOkthIDYIb6FUtnUdLlp hbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VGzT2ouvDzuFYk Res3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U AGegcQCCSA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAw PDEbMBkGA1UEAxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWdu MQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwx GzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjEL MAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGtWhf HZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs49oh gHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sW v+bznkqH7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ue Mv5WJDmyVIRD9YTC2LxBkMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr 9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d19guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt 6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUwAwEB/zBEBgNVHR8EPTA7 MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29tU2lnblNl Y3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58 ADsAj8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkq hkiG9w0BAQUFAAOCAQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7p iL1DRYHjZiM/EoZNGeQFsOY3wo3aBijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtC dsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtpFhpFfTMDZflScZAmlaxMDPWL kz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP51qJThRv4zdL hfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5 7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/ MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW WL1WMRJOEcgh4LMRkWXbtKaIOM5V -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290 IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl 6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+ xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU Cm26OWMohpLzGITY+9HPBVZkVw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I 0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9 B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo IhNzbM8m9Yop5w== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/ BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv 6pZjamVFkpUBtA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG 9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI 2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx 1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV 5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY 1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4 NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91 8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl MrY= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/ oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8 sycX -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/ CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t 9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2 SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd +SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N 0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie 4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1 /YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7 gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/ h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2 9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/ MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw 7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69 ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5 JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03 UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42 tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp /hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0 o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8 PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y Johw1+qRzT65ysCQblrGXnRl11z+o+I= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0 3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8 HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp 3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05 nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNV BAMML0VCRyBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx c8SxMTcwNQYDVQQKDC5FQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXpt ZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAeFw0wNjA4MTcwMDIxMDlaFw0xNjA4 MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25payBTZXJ0aWZpa2Eg SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2ltIFRl a25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h 4fuXd7hxlugTlkaDT7byX3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAk tiHq6yOU/im/+4mRDGSaBUorzAzu8T2bgmmkTPiab+ci2hC6X5L8GCcKqKpE+i4s tPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfreYteIAbTdgtsApWjluTL dlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZTqNGFav4 c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8Um TDGyY5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z +kI2sSXFCjEmN1ZnuqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0O Lna9XvNRiYuoP1Vzv9s6xiQFlpJIqkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMW OeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vmExH8nYQKE3vwO9D8owrXieqW fo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0Nokb+Clsi7n2 l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB /wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgw FoAU587GT/wWZ5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+ 8ygjdsZs93/mQJ7ANtyVDR2tFcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI 6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgmzJNSroIBk5DKd8pNSe/iWtkqvTDO TLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64kXPBfrAowzIpAoHME wfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqTbCmY Iai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJn xk1Gj7sURT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4Q DgZxGhBM/nV+/x5XOULK1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9q Kd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11t hie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQY9iJSrSq3RZj9W6+YKH4 7ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9AahH3eU7 QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB 8zELMAkGA1UEBhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2Vy dGlmaWNhY2lvIChOSUYgUS0wODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1 YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYDVQQLEyxWZWdldSBodHRwczovL3d3 dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UECxMsSmVyYXJxdWlh IEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMTBkVD LUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQG EwJFUzE7MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8g KE5JRiBRLTA4MDExNzYtSSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBD ZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZlZ2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQu bmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJhcnF1aWEgRW50aXRhdHMg ZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUNDMIIBIjAN BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R 85iKw5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm 4CgPukLjbo73FCeTae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaV HMf5NLWUhdWZXqBIoH7nF2W4onW4HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNd QlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0aE9jD2z3Il3rucO2n5nzbcc8t lGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw0JDnJwIDAQAB o4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4 opvpXY0wfwYDVR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBo dHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidW ZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAwDQYJKoZIhvcN AQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJlF7W2u++AVtd0x7Y /X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNaAl6k SBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhy Rp/7SNVel+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOS Agu+TGbrIP65y7WZf+a2E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xl nJ2lYJU6Un/10asIbvPuW/mIPX64b24D5EI= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1 MQswCQYDVQQGEwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1 czEoMCYGA1UEAwwfRUUgQ2VydGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYG CSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIwMTAxMDMwMTAxMDMwWhgPMjAzMDEy MTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlBUyBTZXJ0aWZpdHNl ZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRyZSBS b290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEB AQUAA4IBDwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUy euuOF0+W2Ap7kaJjbMeMTC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvO bntl8jixwKIy72KyaOBhU8E2lf/slLo2rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIw WFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw93X2PaRka9ZP585ArQ/d MtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtNP2MbRMNE 1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYD VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/ zQas8fElyalL1BSZMEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYB BQUHAwMGCCsGAQUFBwMEBggrBgEFBQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEF BQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+RjxY6hUFaTlrg4wCQiZrxTFGGV v9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqMlIpPnTX/dqQG E5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIW iAYLtqZLICjU3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/v GVCJYMzpJJUPwssd8m92kMfMdcGWxZ0= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3 MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3 LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/ HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH 4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+ bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er fF6adulZkMV8gzURZVE= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0 Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4 4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9 KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi 94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP 9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/ eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m 0vdXcDazv/wor3ElhVsT/h5/WrQ8 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3 d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0 L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50 cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0 aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1 U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0 jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/ jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v 1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0 ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1 TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/ gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2 j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6 5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS /jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D hNQ+IIX3Sj0rnP0qCglN6oH4EZw= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c 77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 +GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8 Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL 5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7 S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe 2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv /NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0 abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz 4iIprn2DQKi6bA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9 AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0 7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1 6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl 4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2 MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0 eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz rD6ogRLQy7rQkgu2npaqBA+K -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0 BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz +uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn 5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G spki4cErx5z481+oghLrGREt -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0 IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8 cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+ nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB /wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG 9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9 ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1 c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81 WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73 y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4 Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m 1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH 6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0 IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3 MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7 G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2 zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4 ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2 Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r 6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z 09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs ewv4n4Q= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc 8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg 515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO xwy8p2Fp8fc74SrL+SvzZpA3 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1 MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8 eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG 3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO 291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7 TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4 MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8 RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK 6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH WD9f -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH /PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu 9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo 2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI 4uJEvlz36hz1 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1 dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD 75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp 5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p 6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8 TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7 dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI l7WdmplNsDz4SgCbZN2fOUvRJ9e4 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi AmvZWg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT 3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU +ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1 bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB /zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH 6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93 nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3 +wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG 4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A 7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0 MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7 ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF /YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R 3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy 9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ 2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/ BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9 TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5 +bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv 8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYT AkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQ TS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG 9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMB4XDTAyMTIxMzE0MjkyM1oXDTIw MTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAM BgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEO MAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2 LmZyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaI s9z4iPf930Pfeo2aSVz2TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2 xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCWSo7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4 u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYyHF2fYPepraX/z9E0+X1b F8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNdfrGoRpAx Vs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGd PDPQtQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNV HSAEDjAMMAoGCCqBegF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAx NjAfBgNVHSMEGDAWgBSjBS8YYFDCiQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUF AAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RKq89toB9RlPhJy3Q2FLwV3duJ L92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3QMZsyK10XZZOY YLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2a NjSaTFR+FwNIlQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R 0982gaEbeC9xs/FZTEYYKKuF0mBWWg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4 MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6 ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+ JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+ HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56 awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/ QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+ naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcN AQkBFglwa2lAc2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZp dHNlZXJpbWlza2Vza3VzMRAwDgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMw MVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMQsw CQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEQ MA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB AIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOB SvZiF3tfTQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkz ABpTpyHhOEvWgxutr2TC+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvH LCu3GFH+4Hv2qEivbDtPL+/40UceJlfwUR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMP PbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDaTpxt4brNj3pssAki14sL 2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQFMAMBAf8w ggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwIC MIHDHoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDk AGwAagBhAHMAdABhAHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0 AHMAZQBlAHIAaQBtAGkAcwBrAGUAcwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABz AGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABrAGkAbgBuAGkAdABhAG0AaQBz AGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nwcy8wKwYDVR0f BCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcY P2/v6X2+MA4GA1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOi CfP+JmeaUOTDBS8rNXiRTHyoERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+g kcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyLabVAyJRld/JXIWY7zoVAtjNjGr95 HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678IIbsSt4beDI3poHS na9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkhMp6q qIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0Z TbvGRNs2yyqcjg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0 ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7 N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1 +rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775 tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c 2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAw cjELMAkGA1UEBhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNy b3NlYyBMdGQuMRQwEgYDVQQLEwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9z ZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0MDYxMjI4NDRaFw0xNzA0MDYxMjI4 NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEWMBQGA1UEChMN TWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMTGU1p Y3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw ggEKAoIBAQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2u uO/TEdyB5s87lozWbxXGd36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+ LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/NoqdNAoI/gqyFxuEPkEeZlApxcpMqyabA vjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjcQR/Ji3HWVBTji1R4P770 Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJPqW+jqpx 62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcB AQRbMFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3Aw LQYIKwYBBQUHMAKGIWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAP BgNVHRMBAf8EBTADAQH/MIIBcwYDVR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIB AQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3LmUtc3ppZ25vLmh1L1NaU1ov MIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0AdAB2AOEAbgB5 ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABT AHoAbwBsAGcA4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABh ACAAcwB6AGUAcgBpAG4AdAAgAGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABo AHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMAegBpAGcAbgBvAC4AaAB1AC8AUwBa AFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6Ly93d3cuZS1zemln bm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NOPU1p Y3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxP PU1pY3Jvc2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZv Y2F0aW9uTGlzdDtiaW5hcnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuB EGluZm9AZS1zemlnbm8uaHWkdzB1MSMwIQYDVQQDDBpNaWNyb3NlYyBlLVN6aWdu w7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhTWjEWMBQGA1UEChMNTWlj cm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhVMIGsBgNV HSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJI VTERMA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDAS BgNVBAsTC2UtU3ppZ25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBS b290IENBghEAzLjnv04pGv2i3GalHCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS 8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMTnGZjWS7KXHAM/IO8VbH0jgds ZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FEaGAHQzAxQmHl 7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a 86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfR hUZLphK3dehKyVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/ MPMMNz7UwiiAc7EBt51alhQBS6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3 MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5 VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2 BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C +C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4 qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8 6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/ h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH /nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2 w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg 4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9 4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2 ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8 vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ /L7fCg0= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIJhjCCB26gAwIBAgIBCzANBgkqhkiG9w0BAQsFADCCAR4xPjA8BgNVBAMTNUF1 dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIFJhaXogZGVsIEVzdGFkbyBWZW5lem9s YW5vMQswCQYDVQQGEwJWRTEQMA4GA1UEBxMHQ2FyYWNhczEZMBcGA1UECBMQRGlz dHJpdG8gQ2FwaXRhbDE2MDQGA1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0 aWZpY2FjaW9uIEVsZWN0cm9uaWNhMUMwQQYDVQQLEzpTdXBlcmludGVuZGVuY2lh IGRlIFNlcnZpY2lvcyBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9uaWNhMSUwIwYJ KoZIhvcNAQkBFhZhY3JhaXpAc3VzY2VydGUuZ29iLnZlMB4XDTEwMTIyODE2NTEw MFoXDTIwMTIyNTIzNTk1OVowgdExJjAkBgkqhkiG9w0BCQEWF2NvbnRhY3RvQHBy b2NlcnQubmV0LnZlMQ8wDQYDVQQHEwZDaGFjYW8xEDAOBgNVBAgTB01pcmFuZGEx KjAoBgNVBAsTIVByb3ZlZWRvciBkZSBDZXJ0aWZpY2Fkb3MgUFJPQ0VSVDE2MDQG A1UEChMtU2lzdGVtYSBOYWNpb25hbCBkZSBDZXJ0aWZpY2FjaW9uIEVsZWN0cm9u aWNhMQswCQYDVQQGEwJWRTETMBEGA1UEAxMKUFNDUHJvY2VydDCCAiIwDQYJKoZI hvcNAQEBBQADggIPADCCAgoCggIBANW39KOUM6FGqVVhSQ2oh3NekS1wwQYalNo9 7BVCwfWMrmoX8Yqt/ICV6oNEolt6Vc5Pp6XVurgfoCfAUFM+jbnADrgV3NZs+J74 BCXfgI8Qhd19L3uA3VcAZCP4bsm+lU/hdezgfl6VzbHvvnpC2Mks0+saGiKLt38G ieU89RLAu9MLmV+QfI4tL3czkkohRqipCKzx9hEC2ZUWno0vluYC3XXCFCpa1sl9 JcLB/KpnheLsvtF8PPqv1W7/U0HU9TI4seJfxPmOEO8GqQKJ/+MMbpfg353bIdD0 PghpbNjU5Db4g7ayNo+c7zo3Fn2/omnXO1ty0K+qP1xmk6wKImG20qCZyFSTXai2 0b1dCl53lKItwIKOvMoDKjSuc/HUtQy9vmebVOvh+qBa7Dh+PsHMosdEMXXqP+UH 0quhJZb25uSgXTcYOWEAM11G1ADEtMo88aKjPvM6/2kwLkDd9p+cJsmWN63nOaK/ 6mnbVSKVUyqUtd+tFjiBdWbjxywbk5yqjKPK2Ww8F22c3HxT4CAnQzb5EuE8XL1m v6JpIzi4mWCZDlZTOpx+FIywBm/xhnaQr/2v/pDGj59/i5IjnOcVdo/Vi5QTcmn7 K2FjiO/mpF7moxdqWEfLcU8UC17IAggmosvpr2uKGcfLFFb14dq12fy/czja+eev bqQ34gcnAgMBAAGjggMXMIIDEzASBgNVHRMBAf8ECDAGAQH/AgEBMDcGA1UdEgQw MC6CD3N1c2NlcnRlLmdvYi52ZaAbBgVghl4CAqASDBBSSUYtRy0yMDAwNDAzNi0w MB0GA1UdDgQWBBRBDxk4qpl/Qguk1yeYVKIXTC1RVDCCAVAGA1UdIwSCAUcwggFD gBStuyIdxuDSAaj9dlBSk+2YwU2u06GCASakggEiMIIBHjE+MDwGA1UEAxM1QXV0 b3JpZGFkIGRlIENlcnRpZmljYWNpb24gUmFpeiBkZWwgRXN0YWRvIFZlbmV6b2xh bm8xCzAJBgNVBAYTAlZFMRAwDgYDVQQHEwdDYXJhY2FzMRkwFwYDVQQIExBEaXN0 cml0byBDYXBpdGFsMTYwNAYDVQQKEy1TaXN0ZW1hIE5hY2lvbmFsIGRlIENlcnRp ZmljYWNpb24gRWxlY3Ryb25pY2ExQzBBBgNVBAsTOlN1cGVyaW50ZW5kZW5jaWEg ZGUgU2VydmljaW9zIGRlIENlcnRpZmljYWNpb24gRWxlY3Ryb25pY2ExJTAjBgkq hkiG9w0BCQEWFmFjcmFpekBzdXNjZXJ0ZS5nb2IudmWCAQowDgYDVR0PAQH/BAQD AgEGME0GA1UdEQRGMESCDnByb2NlcnQubmV0LnZloBUGBWCGXgIBoAwMClBTQy0w MDAwMDKgGwYFYIZeAgKgEgwQUklGLUotMzE2MzUzNzMtNzB2BgNVHR8EbzBtMEag RKBChkBodHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9sY3IvQ0VSVElGSUNBRE8t UkFJWi1TSEEzODRDUkxERVIuY3JsMCOgIaAfhh1sZGFwOi8vYWNyYWl6LnN1c2Nl cnRlLmdvYi52ZTA3BggrBgEFBQcBAQQrMCkwJwYIKwYBBQUHMAGGG2h0dHA6Ly9v Y3NwLnN1c2NlcnRlLmdvYi52ZTBBBgNVHSAEOjA4MDYGBmCGXgMBAjAsMCoGCCsG AQUFBwIBFh5odHRwOi8vd3d3LnN1c2NlcnRlLmdvYi52ZS9kcGMwDQYJKoZIhvcN AQELBQADggIBACtZ6yKZu4SqT96QxtGGcSOeSwORR3C7wJJg7ODU523G0+1ng3dS 1fLld6c2suNUvtm7CpsR72H0xpkzmfWvADmNg7+mvTV+LFwxNG9s2/NkAZiqlCxB 3RWGymspThbASfzXg0gTB1GEMVKIu4YXx2sviiCtxQuPcD4quxtxj7mkoP3Yldmv Wb8lK5jpY5MvYB7Eqvh39YtsL+1+LrVPQA3uvFd359m21D+VJzog1eWuq2w1n8Gh HVnchIHuTQfiSLaeS5UtQbHh6N5+LwUeaO6/u5BlOsju6rEYNxxik6SgMexxbJHm pHmJWhSnFFAFTKQAVzAswbVhltw+HoSvOULP5dAssSS830DD7X9jSr3hTxJkhpXz sOfIt+FTvZLm8wyWuevo5pLtp4EJFAv8lXrPj9Y0TzYS3F7RNHXGRoAvlQSMx4bE qCaJqD8Zm4G7UaRKhqsLEQ+xrmNTbSjq3TNWOByyrYDT13K9mmyZY+gAu0F2Bbdb mRiKw7gSXFbPVgx96OLP7bx0R/vu0xdOIk9W/1DzLuY5poLWccret9W6aAjtmcz9 opLLabid+Qqkpj5PkygqYWwHJgD/ll9ohri4zspV4KuxPX+Y1zMOWj3YeMLEYC/H YvBhkdI4sPaeVdtAgAUSM84dkpvRabP/v/GSCmE1P93+hvS84Bpxs2Km -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00 MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341 68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh 4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc 3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2 cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5 YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2 8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp +ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1 ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og /zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2 A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y 4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza 8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+ O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1 o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz 8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l 7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66 AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE +V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4 WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB 4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd 8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A 4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0 aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0 aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0 7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd +LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B 4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57 k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK 4SVhM7JZG+Ju1zdXtg2pEto= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00 MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR /xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+ ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP 0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf 3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl 8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+ DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/ ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJF UzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJ R1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcN MDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3WjBoMQswCQYDVQQGEwJFUzEfMB0G A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScw JQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+ WmmmO3I2F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKj SgbwJ/BXufjpTjJ3Cj9BZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGl u6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQD0EbtFpKd71ng+CT516nDOeB0/RSrFOy A8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXteJajCq+TA81yc477OMUxk Hl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMBAAGjggM7 MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBr aS5ndmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIIC IwYKKwYBBAG/VQIBADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8A cgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIA YQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIAYQBsAGkAdABhAHQAIABWAGEA bABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQByAGEAYwBpAPMA bgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMA aQBvAG4AYQBtAGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQA ZQAgAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEA YwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBuAHQAcgBhACAAZQBuACAAbABhACAA ZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAAOgAvAC8AdwB3AHcA LgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0dHA6 Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+y eAT8MIGVBgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQsw CQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0G A1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVu Y2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRhTvW1yEICKrNcda3Fbcrn lD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdzCkj+IHLt b8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg 9J63NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XF ducTZnV+ZfsBn5OHiJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmC IoaZM3Fa6hlXPZHNqcCjbgcTpsnt+GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa /FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7 sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0 MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8 h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9 UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni 8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5 pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN QSdJQO7e5iNEOdyhIta6A/I= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO 0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj 7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS 8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB /zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3 6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/ 3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR 3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11 bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5 bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1 VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+ Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3 DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8 t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy 1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/ SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIGGTCCBAGgAwIBAgIIPtVRGeZNzn4wDQYJKoZIhvcNAQELBQAwajEhMB8GA1UE AxMYU0cgVFJVU1QgU0VSVklDRVMgUkFDSU5FMRwwGgYDVQQLExMwMDAyIDQzNTI1 Mjg5NTAwMDIyMRowGAYDVQQKExFTRyBUUlVTVCBTRVJWSUNFUzELMAkGA1UEBhMC RlIwHhcNMTAwOTA2MTI1MzQyWhcNMzAwOTA1MTI1MzQyWjBqMSEwHwYDVQQDExhT RyBUUlVTVCBTRVJWSUNFUyBSQUNJTkUxHDAaBgNVBAsTEzAwMDIgNDM1MjUyODk1 MDAwMjIxGjAYBgNVBAoTEVNHIFRSVVNUIFNFUlZJQ0VTMQswCQYDVQQGEwJGUjCC AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANqoVgLsfJXwTukK0rcHoyKL ULO5Lhk9V9sZqtIr5M5C4myh5F0lHjMdtkXRtPpZilZwyW0IdmlwmubHnAgwE/7m 0ZJoYT5MEfJu8rF7V1ZLCb3cD9lxDOiaN94iEByZXtaxFwfTpDktwhpz/cpLKQfC eSnIyCauLMT8I8hL4oZWDyj9tocbaF85ZEX9aINsdSQePHWZYfrSFPipS7HYfad4 0hNiZbXWvn5qA7y1svxkMMPQwpk9maTTzdGxxFOHe0wTE2Z/v9VlU2j5XB7ltP82 mUWjn2LAfxGCAVTeD2WlOa6dSEyJoxA74OaD9bDaLB56HFwfAKzMq6dgZLPGxXvH VUZ0PJCBDkqOWZ1UsEixUkw7mO6r2jS3U81J2i/rlb4MVxH2lkwEeVyZ1eXkvm/q R+5RS+8iJq612BGqQ7t4vwt+tN3PdB0lqYljseI0gcSINTjiAg0PE8nVKoIV8IrE QzJW5FMdHay2z32bll0eZOl0c8RW5BZKUm2SOdPhTQ4/YrnerbUdZbldUv5dCamc tKQM2S9FdqXPjmqanqqwEaHrYcbrPx78ZrQSnUZ/MhaJvnFFr5Eh2f2Tv7QCkUL/ SR/tixVo3R+OrJvdggWcRGkWZBdWX0EPSk8ED2VQhpOX7EW/XcIc3M/E2DrmeAXQ xVVVqV7+qzohu+VyFPcLAgMBAAGjgcIwgb8wHQYDVR0OBBYEFCkgy/HDD9oGjhOT h/5fYBopu/O2MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUKSDL8cMP2gaO E5OH/l9gGim787YwEQYDVR0gBAowCDAGBgRVHSAAMEkGA1UdHwRCMEAwPqA8oDqG OGh0dHA6Ly9jcmwuc2d0cnVzdHNlcnZpY2VzLmNvbS9yYWNpbmUtR3JvdXBlU0cv TGF0ZXN0Q1JMMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEATEZn 4ERQ9cW2urJRCiUTHbfHiC4fuStkoMuTiFJZqmD1zClSF/8E5ze0MRFGfisebKeL PEeaXvSqXZA7RT2fSsmKe47A7j55i5KjyJRKuCgRa6YlX129x8j7g09VMeZc8BN8 471/Kiw3N5RJr4QfFCeiWBCPCjk3GhIgQY8Z9qkfGe2yNLKtfTNEi18KB0PydkVF La3kjQ4A/QQIqudr+xe9sAhWDjUqcvCz5006Tw3c82ASszhkjNv54SaNL+9O6CRH PjY0imkPKGuLh8a9hSb50+tpIVZgkdb34GLCqHGuLt5mI7VSRqakSDcsfwEWVxH3 Jw0O5Q/WkEXhHj8h3NL8FhgTPk1qsiZqQF4leP049KxYejcbmEAEx47J1MRnYbGY rvDNDty5r2WDewoEij9hqvddQYbmxkzCTzpcVuooO6dEz8hKZPVyYC3jQ7hK4HU8 MuSqFtcRucFF2ZtmY2blIrc07rrVdC8lZPOBVMt33lfUk+OsBzE6PlwDg1dTx/D+ aNglUE0SyObhlY1nqzyTPxcCujjXnvcwpT09RAEzGpqfjtCf8e4wiHPvriQZupdz FcHscQyEZLV77LxpPqRtCRY2yko5isune8YdfucziMm+MG2chZUh6Uc7Bn6B4upG 5nBYgOao8p0LadEziVkw82TTC/bOKwn7fRB2LhA= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS /ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH 1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB /zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7 MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u 2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6 Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8 FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc 7uzXLg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291 qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp 5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy 5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv 6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6 B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/ BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen 5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897 IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL +63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR 9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az 5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8 6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7 Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8 Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh /WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw 0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq 4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR 1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/ QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM 94B7IWcnMFk= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6 b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1 HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0 HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3 4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg 8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1 mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5 MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2 8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk 6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn 0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN sSi6 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEW MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM3WhcNMzYwOTE3MTk0NjM2WjB9 MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w +2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+ Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3 Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B 26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID AQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFul F2mHMMo0aEPQQa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCC ATgwLgYIKwYBBQUHAgEWImh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5w ZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cuc3RhcnRzc2wuY29tL2ludGVybWVk aWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENvbW1lcmNpYWwgKFN0 YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0aGUg c2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0 aWZpY2F0aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93 d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgG CWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1 dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5fPGFf59Jb2vKXfuM/gTF wWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWmN3PH/UvS Ta0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst 0OcNOrg+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNc pRJvkrKTlMeIFw6Ttn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKl CcWw0bdT82AUuoVpaiF8H3VhFyAXe2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVF P0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA2MFrLH9ZXF2RsXAiV+uKa0hK 1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBsHvUwyKMQ5bLm KhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ 8dCAWZvLMdibD4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnm fyWl8kgAwKQB2j8= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEW MBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlm aWNhdGlvbiBBdXRob3JpdHkgRzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1 OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjEsMCoG A1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgRzIwggIiMA0G CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8Oo1XJ JZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsD vfOpL9HG4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnoo D/Uefyf3lLE3PbfHkffiAez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/ Q0kGi4xDuFby2X8hQxfqp0iVAXV16iulQ5XqFYSdCI0mblWbq9zSOdIxHWDirMxW RST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbsO+wmETRIjfaAKxojAuuK HDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8HvKTlXcxN nw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM 0D4LnMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/i UUjXuG+v+E5+M5iSFGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9 Ha90OrInwMEePnWjFqmveiJdnxMaz6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHg TuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE AwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJKoZIhvcNAQEL BQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K 2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfX UfEpY9Z1zRbkJ4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl 6/2o1PXWT6RbdejF0mCy2wl+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK 9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG/+gyRr61M3Z3qAFdlsHB1b6uJcDJ HgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTcnIhT76IxW1hPkWLI wpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/XldblhY XzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5l IxKVCCIcl85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoo hdVddLHRDiBYmxOlsGOm7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulr so8uBtjRkcfGEvRM/TAXw8HaOFvjqermobp573PYtlNXLfbQ4ddI -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEezCCA2OgAwIBAgIQNxkY5lNUfBq1uMtZWts1tzANBgkqhkiG9w0BAQUFADCB rjELMAkGA1UEBhMCREUxIDAeBgNVBAgTF0JhZGVuLVd1ZXJ0dGVtYmVyZyAoQlcp MRIwEAYDVQQHEwlTdHV0dGdhcnQxKTAnBgNVBAoTIERldXRzY2hlciBTcGFya2Fz c2VuIFZlcmxhZyBHbWJIMT4wPAYDVQQDEzVTLVRSVVNUIEF1dGhlbnRpY2F0aW9u IGFuZCBFbmNyeXB0aW9uIFJvb3QgQ0EgMjAwNTpQTjAeFw0wNTA2MjIwMDAwMDBa Fw0zMDA2MjEyMzU5NTlaMIGuMQswCQYDVQQGEwJERTEgMB4GA1UECBMXQmFkZW4t V3VlcnR0ZW1iZXJnIChCVykxEjAQBgNVBAcTCVN0dXR0Z2FydDEpMCcGA1UEChMg RGV1dHNjaGVyIFNwYXJrYXNzZW4gVmVybGFnIEdtYkgxPjA8BgNVBAMTNVMtVFJV U1QgQXV0aGVudGljYXRpb24gYW5kIEVuY3J5cHRpb24gUm9vdCBDQSAyMDA1OlBO MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2bVKwdMz6tNGs9HiTNL1 toPQb9UY6ZOvJ44TzbUlNlA0EmQpoVXhOmCTnijJ4/Ob4QSwI7+Vio5bG0F/WsPo TUzVJBY+h0jUJ67m91MduwwA7z5hca2/OnpYH5Q9XIHV1W/fuJvS9eXLg3KSwlOy ggLrra1fFi2SU3bxibYs9cEv4KdKb6AwajLrmnQDaHgTncovmwsdvs91DSaXm8f1 XgqfeN+zvOyauu9VjxuapgdjKRdZYgkqeQd3peDRF2npW932kKvimAoA0SVtnteF hy+S8dF2g08LOlk3KC8zpxdQ1iALCvQm+Z845y2kuJuJja2tyWp9iRe79n+Ag3rm 7QIDAQABo4GSMIGPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEG MCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFTVFJvbmxpbmUxLTIwNDgtNTAdBgNV HQ4EFgQUD8oeXHngovMpttKFswtKtWXsa1IwHwYDVR0jBBgwFoAUD8oeXHngovMp ttKFswtKtWXsa1IwDQYJKoZIhvcNAQEFBQADggEBAK8B8O0ZPCjoTVy7pWMciDMD pwCHpB8gq9Yc4wYfl35UvbfRssnV2oDsF9eK9XvCAPbpEW+EoFolMeKJ+aQAPzFo LtU96G7m1R08P7K9n3frndOMusDXtk3sU5wPBG7qNWdX4wple5A64U8+wwCSersF iXOMy6ZNwPv2AtawB6MDwidAnwzkhYItr5pCHdDHjfhA7p0GVxzZotiAFP7hYy0y h9WUUpY6RsZxlj33mA6ykaqP2vROJAA5VeitF7nTNCtKqUDMFypVZUF0Qn71wK/I k63yGFs9iQzbRzkk+OBM8h+wPQrKBU6JIRrjKpms/H+h8Q8bHz2eBIPdltkdOpQ= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID2DCCAsCgAwIBAgIQYFbFSyNAW2TU7SXa2dYeHjANBgkqhkiG9w0BAQsFADCB hTELMAkGA1UEBhMCREUxKTAnBgNVBAoTIERldXRzY2hlciBTcGFya2Fzc2VuIFZl cmxhZyBHbWJIMScwJQYDVQQLEx5TLVRSVVNUIENlcnRpZmljYXRpb24gU2Vydmlj ZXMxIjAgBgNVBAMTGVMtVFJVU1QgVW5pdmVyc2FsIFJvb3QgQ0EwHhcNMTMxMDIy MDAwMDAwWhcNMzgxMDIxMjM1OTU5WjCBhTELMAkGA1UEBhMCREUxKTAnBgNVBAoT IERldXRzY2hlciBTcGFya2Fzc2VuIFZlcmxhZyBHbWJIMScwJQYDVQQLEx5TLVRS VVNUIENlcnRpZmljYXRpb24gU2VydmljZXMxIjAgBgNVBAMTGVMtVFJVU1QgVW5p dmVyc2FsIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCo 4wvfETeFgpq1bGZ8YT/ARxodRuOwVWTluII5KAd+F//0m4rwkYHqOD8heGxI7Gsv otOKcrKn19nqf7TASWswJYmM67fVQGGY4tw8IJLNZUpynxqOjPolFb/zIYMoDYuv WRGCQ1ybTSVRf1gYY2A7s7WKi1hjN0hIkETCQN1d90NpKZhcEmVeq5CSS2bf1XUS U1QYpt6K1rtXAzlZmRgFDPn9FcaQZEYXgtfCSkE9/QC+V3IYlHcbU1qJAfYzcg6T OtzoHv0FBda8c+CI3KtP7LUYhk95hA5IKmYq3TLIeGXIC51YAQVx7YH1aBduyw20 S9ih7K446xxYL6FlAzQvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P AQH/BAQDAgEGMB0GA1UdDgQWBBSafdfr639UmEUptCCrbQuWIxmkwjANBgkqhkiG 9w0BAQsFAAOCAQEATpYS2353XpInniEXGIJ22D+8pQkEZoiJrdtVszNqxmXEj03z MjbceQSWqXcy0Zf1GGuMuu3OEdBEx5LxtESO7YhSSJ7V/Vn4ox5R+wFS5V/let2q JE8ii912RvaloA812MoPmLkwXSBvwoEevb3A/hXTOCoJk5gnG5N70Cs0XmilFU/R UsOgyqCDRR319bdZc11ZAY+qwkcvFHHVKeMQtUeTJcwjKdq3ctiR1OwbSIoi5MEq 9zpok59FGW5Dt8z+uJGaYRo2aWNkkijzb2GShROfyQcsi1fc65551cLeCNVUsldO KjKNoeI60RAgIjl9NEVvcTvDHfz/sk+o4vYwHg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9 m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/ TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo 19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e 3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6 MBr1mmz0DlP5OlvRHA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIF2TCCA8GgAwIBAgIQHp4o6Ejy5e/DfEoeWhhntjANBgkqhkiG9w0BAQsFADBk MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0 YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg Q0EgMjAeFw0xMTA2MjQwODM4MTRaFw0zMTA2MjUwNzM4MTRaMGQxCzAJBgNVBAYT AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAyMIICIjAN BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlUJOhJ1R5tMJ6HJaI2nbeHCOFvEr jw0DzpPMLgAIe6szjPTpQOYXTKueuEcUMncy3SgM3hhLX3af+Dk7/E6J2HzFZ++r 0rk0X2s682Q2zsKwzxNoysjL67XiPS4h3+os1OD5cJZM/2pYmLcX5BtS5X4HAB1f 2uY+lQS3aYg5oUFgJWFLlTloYhyxCwWJwDaCFCE/rtuh/bxvHGCGtlOUSbkrRsVP ACu/obvLP+DHVxxX6NZp+MEkUp2IVd3Chy50I9AU/SpHWrumnf2U5NGKpV+GY3aF y6//SSj8gO1MedK75MDvAe5QQQg1I3ArqRa0jG6F6bYRzzHdUyYb3y1aSgJA/MTA tukxGggo5WDDH8SQjhBiYEQN7Aq+VRhxLKX0srwVYv8c474d2h5Xszx+zYIdkeNL 6yxSNLCK/RJOlrDrcH+eOfdmQrGrrFLadkBXeyq96G4DsguAhYidDMfCd7Camlf0 uPoTXGiTOmekl9AbmbeGMktg2M7v0Ax/lZ9vh0+Hio5fCHyqW/xavqGRn1V9TrAL acywlKinh/LTSlDcX3KwFnUey7QYYpqwpzmqm59m2I2mbJYV4+by+PGDYmy7Velh k6M99bFXi08jsJvllGov34zflVEpYKELKeRcVVi3qPyZ7iVNTA6z00yPhOgpD/0Q VAKFyPnlw4vP5w8CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw FDASBgdghXQBUwIBBgdghXQBUwIBMBIGA1UdEwEB/wQIMAYBAf8CAQcwHQYDVR0O BBYEFE0mICKJS9PVpAqhb97iEoHF8TwuMB8GA1UdIwQYMBaAFE0mICKJS9PVpAqh b97iEoHF8TwuMA0GCSqGSIb3DQEBCwUAA4ICAQAyCrKkG8t9voJXiblqf/P0wS4R fbgZPnm3qKhyN2abGu2sEzsOv2LwnN+ee6FTSA5BesogpxcbtnjsQJHzQq0Qw1zv /2BZf82Fo4s9SBwlAjxnffUy6S8w5X2lejjQ82YqZh6NM4OKb3xuqFp1mrjX2lhI REeoTPpMSQpKwhI3qEAMw8jh0FcNlzKVxzqfl9NX+Ave5XLzo9v/tdhZsnPdTSpx srpJ9csc1fV5yJmz/MFMdOO0vSk3FQQoHt5FRnDsr7p4DooqzgB53MBfGWcsa0vv aGgLQ+OswWIJ76bdZWGgr4RVSJFSHMYlkSrQwSIjYVmvRRGFHQEkNI/Ps/8XciAT woCqISxxOQ7Qj1zB09GOInJGTB2Wrk9xseEFKZZZ9LuedT3PDTcNYtsmjGOpI99n Bjx8Oto0QuFmtEYE3saWmA9LSHokMnWRn6z3aOkquVVlzl1h0ydw2Df+n7mvoC5W t6NlUe07qxS/TFED6F+KBZvuim6c779o+sjaC+NCydAXFJy3SuCvkychVSa1ZC+N 8f+mQAWFBVzKBxlcCxMoTFh/wqXvRdpg065lYZ1Tg3TCrvJcwhbtkj6EPnNgiLx2 9CzP0H1907he0ZESEOnN3col49XtmS++dYFLJPlFRpTJKSFTnCZFqhMX5OfNeOI5 wSsSnqaeG8XmDtkx2Q== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIF4DCCA8igAwIBAgIRAPL6ZOJ0Y9ON/RAdBB92ylgwDQYJKoZIhvcNAQELBQAw ZzELMAkGA1UEBhMCY2gxETAPBgNVBAoTCFN3aXNzY29tMSUwIwYDVQQLExxEaWdp dGFsIENlcnRpZmljYXRlIFNlcnZpY2VzMR4wHAYDVQQDExVTd2lzc2NvbSBSb290 IEVWIENBIDIwHhcNMTEwNjI0MDk0NTA4WhcNMzEwNjI1MDg0NTA4WjBnMQswCQYD VQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2Vy dGlmaWNhdGUgU2VydmljZXMxHjAcBgNVBAMTFVN3aXNzY29tIFJvb3QgRVYgQ0Eg MjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMT3HS9X6lds93BdY7Bx UglgRCgzo3pOCvrY6myLURYaVa5UJsTMRQdBTxB5f3HSek4/OE6zAMaVylvNwSqD 1ycfMQ4jFrclyxy0uYAyXhqdk/HoPGAsp15XGVhRXrwsVgu42O+LgrQ8uMIkqBPH oCE2G3pXKSinLr9xJZDzRINpUKTk4RtiGZQJo/PDvO/0vezbE53PnUgJUmfANykR HvvSEaeFGHR55E+FFOtSN+KxRdjMDUN/rhPSays/p8LiqG12W0OfvrSdsyaGOx9/ 5fLoZigWJdBLlzin5M8J0TbDC77aO0RYjb7xnglrPvMyxyuHxuxenPaHZa0zKcQv idm5y8kDnftslFGXEBuGCxobP/YCfnvUxVFkKJ3106yDgYjTdLRZncHrYTNaRdHL OdAGalNgHa/2+2m8atwBz735j9m9W8E6X47aD0upm50qKGsaCnw8qyIL5XctcfaC NYGu+HuB5ur+rPQam3Rc6I8k9l2dRsQs0h4rIWqDJ2dVSqTjyDKXZpBy2uPUZC5f 46Fq9mDU5zXNysRojddxyNMkM3OxbPlq4SjbX8Y96L5V5jcb7STZDxmPX2MYWFCB UWVv8p9+agTnNCRxunZLWB4ZvRVgRaoMEkABnRDixzgHcgplwLa7JSnaFp6LNYth 7eVxV4O1PHGf40+/fh6Bn0GXAgMBAAGjgYYwgYMwDgYDVR0PAQH/BAQDAgGGMB0G A1UdIQQWMBQwEgYHYIV0AVMCAgYHYIV0AVMCAjASBgNVHRMBAf8ECDAGAQH/AgED MB0GA1UdDgQWBBRF2aWBbj2ITY1x0kbBbkUe88SAnTAfBgNVHSMEGDAWgBRF2aWB bj2ITY1x0kbBbkUe88SAnTANBgkqhkiG9w0BAQsFAAOCAgEAlDpzBp9SSzBc1P6x XCX5145v9Ydkn+0UjrgEjihLj6p7jjm02Vj2e6E1CqGdivdj5eu9OYLU43otb98T PLr+flaYC/NUn81ETm484T4VvwYmneTwkLbUwp4wLh/vx3rEUMfqe9pQy3omywC0 Wqu1kx+AiYQElY2NfwmTv9SoqORjbdlk5LgpWgi/UOGED1V7XwgiG/W9mR4U9s70 WBCCswo9GcG/W6uqmdjyMb3lOGbcWAXH7WMaLgqXfIeTK7KK4/HsGOV1timH59yL Gn602MnTihdsfSlEvoqq9X46Lmgxk7lq2prg2+kupYTNHAq4Sgj5nPFhJpiTt3tm 7JFe3VE/23MPrQRYCd0EApUKPtN236YQHoA96M2kZNEzx5LH4k5E4wnJTsJdhw4S nr8PyQUQ3nqjsTzyP6WqJ3mtMX0f/fwZacXduT98zca0wjAefm6S139hdlqP65VN vBFuIXxZN5nQBrz5Bm0yFqXZaajh3DyAHmBR3NdUIR7KYndP+tiPsys6DXhyyWhB WkdKwqPrGtcKqzwyVcgKEZzfdNbwQBUdyLmPtTbFr/giuMod89a2GQ+fYWVq6nTI fI/DT11lgh/ZDYnadXL77/FHZxOzyNEZiCcmmpl5fx7kLD977vHeTYuWl8PVP3wb I+2ksx0WckNLIOFZfsLorSa/ovc= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8 76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+ bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c 6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7 lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn 8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6 45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5 O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a 77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3 92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+ 6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl +zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0 ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0 uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+ FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7 jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/ u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1 puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH 6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/ c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6 5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0 cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9 xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ 2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8 aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/ OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+ hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/ MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2 jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7 hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1 EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl pYYsfPQS -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1 OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK 8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99 5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3 kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6 Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8 au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0 Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1 OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2 1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1 Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6 Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290 Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8 TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6 g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB 95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1 c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1 7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn 8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/ 2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2 MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1 7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+ /jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs 81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4 pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG 9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx 0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7 Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7 vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDNjCCAp+gAwIBAgIQNhIilsXjOKUgodJfTNcJVDANBgkqhkiG9w0BAQUFADCB zjELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJ Q2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UE CxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhh d3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNl cnZlckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIxMDEwMTIzNTk1OVow gc4xCzAJBgNVBAYTAlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcT CUNhcGUgVG93bjEdMBsGA1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNV BAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRo YXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1z ZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2 aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560 ZXUCTe/LCaIhUdib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j +ao6hnO2RlNYyIkFvYMRuHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/ BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQBlkKyID1bZ5jA01CbH0FDxkt5r1DmI CSLGpmODA/eZd9iy5Ri4XWPz1HP7bJyZePFLeH0ZJMMrAoT4vCLZiiLXoPxx7JGH IPG47LHlVYCsPVLIOQ7C8MAFT9aCdYy9X9LcdpoFEsmvcsPcJX6kTY4XpeCHf+Ga WuFg3GQjPEIuTQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta 3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk 6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6 Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2 /qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/ LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7 jVaMaA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/ BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6 papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3 KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8 YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9 9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA 2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu MdRAGmI0Nj81Aa6sY6A= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBF MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQL ExNUcnVzdGlzIEZQUyBSb290IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTEx MzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNVBAoTD1RydXN0aXMgTGltaXRlZDEc MBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD ggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQRUN+ AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihH iTHcDnlkH5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjj vSkCqPoc4Vu5g6hBSLwacY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA 0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zto3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlB OrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEAAaNTMFEwDwYDVR0TAQH/ BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAdBgNVHQ4E FgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01 GX2cGE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmW zaD+vkAMXBJV+JOCyinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP4 1BIy+Q7DsdwyhEQsb8tGD+pmQQ9P8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZE f1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHVl/9D7S3B2l0pKoU/rGXuhg8F jZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYliB6XzCGcKQEN ZetX2fNXlrtIzYE= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1 OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi 1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/ WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6 g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN 9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP BSeOE6Fuwg== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1 OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50 ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN 8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/ RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4 hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5 ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1 A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ 1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30 6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT 91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p TpPDpFQUWw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRS MRgwFgYDVQQHDA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJp bGltc2VsIHZlIFRla25vbG9qaWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSw VEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ryb25payB2ZSBLcmlwdG9sb2ppIEFy YcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNVBAsMGkthbXUgU2Vy dGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUgS8O2 ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAe Fw0wNzA4MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIx GDAWBgNVBAcMD0dlYnplIC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmls aW1zZWwgdmUgVGVrbm9sb2ppayBBcmHFn3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBU QUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZlIEtyaXB0b2xvamkgQXJh xZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2FtdSBTZXJ0 aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7Zr IFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIB IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4h gb46ezzb8R1Sf1n68yJMlaCQvEhOEav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yK O7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1xnnRFDDtG1hba+818qEhTsXO fJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR6Oqeyjh1jmKw lZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQID AQABo0IwQDAdBgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/ BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmP NOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4N5EY3ATIZJkrGG2AA1nJrvhY0D7t wyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLTy9LQQfMmNkqblWwM 7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYhLBOh gLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5n oN+J1q2MdqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUs yZyQ2uypQjyttgI= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8 dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7 XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1 JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51 b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV 9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7 kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS RGQDJereW26fyfJOrN3H -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEPTCCAyWgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvzE/MD0GA1UEAww2VMOc UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV4wXAYDVQQKDFVUw5xS S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg SGl6bWV0bGVyaSBBLsWeLiAoYykgQXJhbMSxayAyMDA3MB4XDTA3MTIyNTE4Mzcx OVoXDTE3MTIyMjE4MzcxOVowgb8xPzA9BgNVBAMMNlTDnFJLVFJVU1QgRWxla3Ry b25payBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTELMAkGA1UEBhMC VFIxDzANBgNVBAcMBkFua2FyYTFeMFwGA1UECgxVVMOcUktUUlVTVCBCaWxnaSDE sGxldGnFn2ltIHZlIEJpbGnFn2ltIEfDvHZlbmxpxJ9pIEhpem1ldGxlcmkgQS7F ni4gKGMpIEFyYWzEsWsgMjAwNzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC ggEBAKu3PgqMyKVYFeaK7yc9SrToJdPNM8Ig3BnuiD9NYvDdE3ePYakqtdTyuTFY KTsvP2qcb3N2Je40IIDu6rfwxArNK4aUyeNgsURSsloptJGXg9i3phQvKUmi8wUG +7RP2qFsmmaf8EMJyupyj+sA1zU511YXRxcw9L6/P8JorzZAwan0qafoEGsIiveG HtyaKhUG9qPw9ODHFNRRf8+0222vR5YXm3dx2KdxnSQM9pQ/hTEST7ruToK4uT6P IzdezKKqdfcYbwnTrqdUKDT74eA7YH2gvnmJhsifLfkKS8RQouf9eRbHegsYz85M 733WB2+Y8a+xwXrXgTW4qhe04MsCAwEAAaNCMEAwHQYDVR0OBBYEFCnFkKslrxHk Yb+j/4hhkeYO/pyBMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G CSqGSIb3DQEBBQUAA4IBAQAQDdr4Ouwo0RSVgrESLFF6QSU2TJ/sPx+EnWVUXKgW AkD6bho3hO9ynYYKVZ1WKKxmLNA6VpM0ByWtCLCPyA8JWcqdmBzlVPi5RX9ql2+I aE1KBiY3iAIOtsbWcpnOa3faYjGkVh+uX4132l32iPwa2Z61gfAyuOOI0JzzaqC5 mxRZNTZPz/OOXl0XrRWV2N2y1RVuAE6zS89mlOTgzbUF2mNXi+WzqtvALhyQRNsa XRik7r4EW5nVcV9VZWRi1aKbBFmGyGJ353yCRWo9F7/snXUMrqNvWtMvmDb08PUZ qxFdyKbjKlhqQgnDvZImZjINXQhVdP+MmNAKpoRq0Tl9 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOc UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xS S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg SGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3 WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVrdHJv bmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJU UjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSw bGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe LiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnef J1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdh R3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJ Qv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGX JHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1p zpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58S Fq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMBAf8wDQYJ KoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq ECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4 Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFz gw2lGh1uEpJ+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotH uFEJjOp9zYhys2AzsfAKRO8P9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LS y3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5UrbnBEI= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5 NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF 10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz 0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc 46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2 yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm 4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB /zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL 1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+ nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh 15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW 6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy KwbQBM0= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx 3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B 3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/ Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2 VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT 79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6 c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3 ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs 8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/ qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG jjxDah2nGN59PRbxYvnKkKj9 -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkG A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G CSqGSIb3DQEBBQUAA4GBAFgVKTk8d6PaXCUDfGD67gmZPCcQcMgMCeazh88K4hiW NWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n0a3hUKw8fGJLj7qE1xIV Gx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZRjXZ+Hxb -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2 MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i 2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ 2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC 4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0 IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF 9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN /BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4 sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+ seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz 4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+ BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3 7M2CYfE45k+XmCpajQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMx IDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxs cyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9v dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0 MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdl bGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQD DC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+r WxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU Dk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcs HqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNj z7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFaf SZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/Slwxl AgMBAAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqG KGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0P AQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0j BIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkGA1UEBhMC VVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX ZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEB ALkVsUSRzCPIK0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd /ZDJPHV3V3p9+N701NX3leZ0bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pB A4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSljqHyita04pO2t/caaH/+Xc/77szWn k4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+esE2fDbbFwRnzVlhE9 iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJtylv 2G0xffX8oRAHh84vWdw+WNs= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFdjCCA16gAwIBAgIQXmjWEXGUY1BWAGjzPsnFkTANBgkqhkiG9w0BAQUFADBV MQswCQYDVQQGEwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxKjAoBgNV BAMTIUNlcnRpZmljYXRpb24gQXV0aG9yaXR5IG9mIFdvU2lnbjAeFw0wOTA4MDgw MTAwMDFaFw0zOTA4MDgwMTAwMDFaMFUxCzAJBgNVBAYTAkNOMRowGAYDVQQKExFX b1NpZ24gQ0EgTGltaXRlZDEqMCgGA1UEAxMhQ2VydGlmaWNhdGlvbiBBdXRob3Jp dHkgb2YgV29TaWduMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvcqN rLiRFVaXe2tcesLea9mhsMMQI/qnobLMMfo+2aYpbxY94Gv4uEBf2zmoAHqLoE1U fcIiePyOCbiohdfMlZdLdNiefvAA5A6JrkkoRBoQmTIPJYhTpA2zDxIIFgsDcScc f+Hb0v1naMQFXQoOXXDX2JegvFNBmpGN9J42Znp+VsGQX+axaCA2pIwkLCxHC1l2 ZjC1vt7tj/id07sBMOby8w7gLJKA84X5KIq0VC6a7fd2/BVoFutKbOsuEo/Uz/4M x1wdC34FMr5esAkqQtXJTpCzWQ27en7N1QhatH/YHGkR+ScPewavVIMYe+HdVHpR aG53/Ma/UkpmRqGyZxq7o093oL5d//xWC0Nyd5DKnvnyOfUNqfTq1+ezEC8wQjch zDBwyYaYD8xYTYO7feUapTeNtqwylwA6Y3EkHp43xP901DfA4v6IRmAR3Qg/UDar uHqklWJqbrDKaiFaafPz+x1wOZXzp26mgYmhiMU7ccqjUu6Du/2gd/Tkb+dC221K mYo0SLwX3OSACCK28jHAPwQ+658geda4BmRkAjHXqc1S+4RFaQkAKtxVi8QGRkvA Sh0JWzko/amrzgD5LkhLJuYwTKVYyrREgk/nkR4zw7CT/xH8gdLKH3Ep3XZPkiWv HYG3Dy+MwwbMLyejSuQOmbp8HkUff6oZRZb9/D0CAwEAAaNCMEAwDgYDVR0PAQH/ BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFOFmzw7R8bNLtwYgFP6H EtX2/vs+MA0GCSqGSIb3DQEBBQUAA4ICAQCoy3JAsnbBfnv8rWTjMnvMPLZdRtP1 LOJwXcgu2AZ9mNELIaCJWSQBnfmvCX0KI4I01fx8cpm5o9dU9OpScA7F9dY74ToJ MuYhOZO9sxXqT2r09Ys/L3yNWC7F4TmgPsc9SnOeQHrAK2GpZ8nzJLmzbVUsWh2e JXLOC62qx1ViC777Y7NhRCOjy+EaDveaBk3e1CNOIZZbOVtXHS9dCF4Jef98l7VN g64N1uajeeAz0JmWAjCnPv/So0M/BVoG6kQC2nz4SNAzqfkHx5Xh9T71XXG68pWp dIhhWeO/yloTunK0jF02h+mmxTwTv97QRCbut+wucPrXnbes5cVAWubXbHssw1ab R80LzvobtCHXt2a49CUwi1wNuepnsvRtrtWhnk/Yn+knArAdBtaP4/tIEp9/EaEQ PkxROpaw0RPxx9gmrjrKkcRpnd8BKWRRb2jaFOwIQZeQjdCygPLPwj2/kWjFgGce xGATVdVhmVd8upUPYUk6ynW8yQqTP2cOEvIo4jEbwFcW3wh8GcF+Dx+FHgo2fFt+ J7x6v+Db9NpSvd4MVHAxkUOVyLzwPt0JfjBkUO1/AaQzZ01oT74V77D2AhGiGxMl OtzCWfHjXEa7ZywCRuoeSKbmW9m1vFGikpbbqsY3Iqb+zCB0oy2pLmvLwIIRIbWT ee5Ehr7XHuQe+w== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIFWDCCA0CgAwIBAgIQUHBrzdgT/BtOOzNy0hFIjTANBgkqhkiG9w0BAQsFADBG MQswCQYDVQQGEwJDTjEaMBgGA1UEChMRV29TaWduIENBIExpbWl0ZWQxGzAZBgNV BAMMEkNBIOayg+mAmuagueivgeS5pjAeFw0wOTA4MDgwMTAwMDFaFw0zOTA4MDgw MTAwMDFaMEYxCzAJBgNVBAYTAkNOMRowGAYDVQQKExFXb1NpZ24gQ0EgTGltaXRl ZDEbMBkGA1UEAwwSQ0Eg5rKD6YCa5qC56K+B5LmmMIICIjANBgkqhkiG9w0BAQEF AAOCAg8AMIICCgKCAgEA0EkhHiX8h8EqwqzbdoYGTufQdDTc7WU1/FDWiD+k8H/r D195L4mx/bxjWDeTmzj4t1up+thxx7S8gJeNbEvxUNUqKaqoGXqW5pWOdO2XCld1 9AXbbQs5uQF/qvbW2mzmBeCkTVL829B0txGMe41P/4eDrv8FAxNXUDf+jJZSEExf v5RxadmWPgxDT74wwJ85dE8GRV2j1lY5aAfMh09Qd5Nx2UQIsYo06Yms25tO4dnk UkWMLhQfkWsZHWgpLFbE4h4TV2TwYeO5Ed+w4VegG63XX9Gv2ystP9Bojg/qnw+L NVgbExz03jWhCl3W6t8Sb8D7aQdGctyB9gQjF+BNdeFyb7Ao65vh4YOhn0pdr8yb +gIgthhid5E7o9Vlrdx8kHccREGkSovrlXLp9glk3Kgtn3R46MGiCWOc76DbT52V qyBPt7D3h1ymoOQ3OMdc4zUPLK2jgKLsLl3Az+2LBcLmc272idX10kaO6m1jGx6K yX2m+Jzr5dVjhU1zZmkR/sgO9MHHZklTfuQZa/HpelmjbX7FF+Ynxu8b22/8DU0G AbQOXDBGVWCvOGU6yke6rCzMRh+yRpY/8+0mBe53oWprfi1tWFxK1I5nuPHa1UaK J/kR8slC/k7e3x9cxKSGhxYzoacXGKUN5AXlK8IrC6KVkLn9YDxOiT7nnO4fuwEC AwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O BBYEFOBNv9ybQV0T6GTwp+kVpOGBwboxMA0GCSqGSIb3DQEBCwUAA4ICAQBqinA4 WbbaixjIvirTthnVZil6Xc1bL3McJk6jfW+rtylNpumlEYOnOXOvEESS5iVdT2H6 yAa+Tkvv/vMx/sZ8cApBWNromUuWyXi8mHwCKe0JgOYKOoICKuLJL8hWGSbueBwj /feTZU7n85iYr83d2Z5AiDEoOqsuC7CsDCT6eiaY8xJhEPRdF/d+4niXVOKM6Cm6 jBAyvd0zaziGfjk9DgNyp115j0WKWa5bIW4xRtVZjc8VX90xJc/bYNaBRHIpAlf2 ltTW/+op2znFuCyKGo3Oy+dCMYYFaA6eFN0AkLppRQjbbpCBhqcqBT/mhDn4t/lX X0ykeVoQDF7Va/81XwVRHmyjdanPUIPTfPRm94KNPQx96N97qA4bLJyuQHCH2u2n FoJavjVsIE4iYdm8UXrNemHcSxH5/mc0zy4EZmFcV5cjjPOGG0jfKq+nwf/Yjj4D u9gqsPoUJbJRa4ZDhS4HIxaAjUz7tGM7zMN07RujHv41D198HRaG9Q7DlfEvr10l O1Hm13ZBONFLAzkopR6RctR9q5czxNM+4Gm2KHmgCY0c0f9BckgG/Jou5yD5m6Le ie2uPAmvylezkolwQOQvT8Jwg0DXJCxr5wkf09XHwQj02w47HAcLQxGEIYbpgNR1 2KvxAmLBsX5VYc8T1yaw15zLKYs4SgsOkI26oQ== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIIEMDCCA5mgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBxzELMAkGA1UEBhMCVVMx FzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMR8wHQYDVQQHExZSZXNlYXJjaCBUcmlh bmdsZSBQYXJrMRYwFAYDVQQKEw1SZWQgSGF0LCBJbmMuMSEwHwYDVQQLExhSZWQg SGF0IE5ldHdvcmsgU2VydmljZXMxIzAhBgNVBAMTGlJITlMgQ2VydGlmaWNhdGUg QXV0aG9yaXR5MR4wHAYJKoZIhvcNAQkBFg9yaG5zQHJlZGhhdC5jb20wHhcNMDAw ODIzMjI0NTU1WhcNMDMwODI4MjI0NTU1WjCBxzELMAkGA1UEBhMCVVMxFzAVBgNV BAgTDk5vcnRoIENhcm9saW5hMR8wHQYDVQQHExZSZXNlYXJjaCBUcmlhbmdsZSBQ YXJrMRYwFAYDVQQKEw1SZWQgSGF0LCBJbmMuMSEwHwYDVQQLExhSZWQgSGF0IE5l dHdvcmsgU2VydmljZXMxIzAhBgNVBAMTGlJITlMgQ2VydGlmaWNhdGUgQXV0aG9y aXR5MR4wHAYJKoZIhvcNAQkBFg9yaG5zQHJlZGhhdC5jb20wgZ8wDQYJKoZIhvcN AQEBBQADgY0AMIGJAoGBAMBoKxIw4iEtIsZycVu/F6CTEOmb48mNOy2sxLuVO+DK VTLclcIQswSyUfvohWEWNKW0HWdcp3f08JLatIuvlZNi82YprsCIt2SEDkiQYPhg PgB/VN0XpqwY4ELefL6Qgff0BYUKCMzV8p/8JIt3pT3pSKnvDztjo/6mg0zo3At3 AgMBAAGjggEoMIIBJDAdBgNVHQ4EFgQUVBXNnyz37A0f0qi+TAesiD77mwowgfQG A1UdIwSB7DCB6YAUVBXNnyz37A0f0qi+TAesiD77mwqhgc2kgcowgccxCzAJBgNV BAYTAlVTMRcwFQYDVQQIEw5Ob3J0aCBDYXJvbGluYTEfMB0GA1UEBxMWUmVzZWFy Y2ggVHJpYW5nbGUgUGFyazEWMBQGA1UEChMNUmVkIEhhdCwgSW5jLjEhMB8GA1UE CxMYUmVkIEhhdCBOZXR3b3JrIFNlcnZpY2VzMSMwIQYDVQQDExpSSE5TIENlcnRp ZmljYXRlIEF1dGhvcml0eTEeMBwGCSqGSIb3DQEJARYPcmhuc0ByZWRoYXQuY29t ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAkwGIiGdnkYye0BIU kHESh1UK8lIbrfLTBx2vcJm7sM2AI8ntK3PpY7HQs4xgxUJkpsGVVpDFNQYDWPWO K9n5qaAQqZn3FUKSpVDXEQfxAtXgcORVbirOJfhdzQsvEGH49iBCzMOJ+IpPgiQS zzl/IagsjVKXUsX3X0KlhwlmsMw= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID7jCCA1egAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsTELMAkGA1UEBhMCVVMx FzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRAwDgYDVQQHEwdSYWxlaWdoMRYwFAYD VQQKEw1SZWQgSGF0LCBJbmMuMRgwFgYDVQQLEw9SZWQgSGF0IE5ldHdvcmsxIjAg BgNVBAMTGVJITiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEW EnJobi1ub2NAcmVkaGF0LmNvbTAeFw0wMjA5MDUyMDQ1MTZaFw0wNzA5MDkyMDQ1 MTZaMIGxMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAO BgNVBAcTB1JhbGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsT D1JlZCBIYXQgTmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhv cml0eTEhMB8GCSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tMIGfMA0GCSqG SIb3DQEBAQUAA4GNADCBiQKBgQCzFrfF9blpUR/NtD1wz2BXhaQqp10oIg7sGeKS 90iXpqYfUZWDEY+amKKQ4MtKJBmUqIpLiLQGbM531xU7PM1mg88jHQ28CgzLH8tA +/PZ/iq0hSx7yaH+849oHfISsaQWGc4PuJqc2bxfSWKylZPOXS7deTzxW6a3orU5 DY4SMQIDAQABo4IBEjCCAQ4wHQYDVR0OBBYEFH8bZKEuAsWofbjRsYsGnaOpUGOS MIHeBgNVHSMEgdYwgdOAFH8bZKEuAsWofbjRsYsGnaOpUGOSoYG3pIG0MIGxMQsw CQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAOBgNVBAcTB1Jh bGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsTD1JlZCBIYXQg TmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhvcml0eTEhMB8G CSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tggEAMAwGA1UdEwQFMAMBAf8w DQYJKoZIhvcNAQEEBQADgYEAKE1C5TQi3caGYwR1UmcXRXLyOyErRVlyc/dZNp1X Q8bclA8O/xNcT1A3hbLkwh81n3T051P7oQa4Oc7kCoZ7XyhdxxGeEqXWuWzpGAnV 8ELnVLWRniOtEnqqcnw5PIP4daR7A5L/KtTFdhkS+rQ7sIkslYwBkA3YugYFYQCs ldo= -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- MIID7jCCA1egAwIBAgIBADANBgkqhkiG9w0BAQQFADCBsTELMAkGA1UEBhMCVVMx FzAVBgNVBAgTDk5vcnRoIENhcm9saW5hMRAwDgYDVQQHEwdSYWxlaWdoMRYwFAYD VQQKEw1SZWQgSGF0LCBJbmMuMRgwFgYDVQQLEw9SZWQgSGF0IE5ldHdvcmsxIjAg BgNVBAMTGVJITiBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEW EnJobi1ub2NAcmVkaGF0LmNvbTAeFw0wMzA4MjkwMjEwNTVaFw0xMzA4MjYwMjEw NTVaMIGxMQswCQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAO BgNVBAcTB1JhbGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsT D1JlZCBIYXQgTmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhv cml0eTEhMB8GCSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tMIGfMA0GCSqG SIb3DQEBAQUAA4GNADCBiQKBgQC/YWPrPYsrRUjmwvt80iEhuOyQk0EwfCyNedUU 6Q5+P+/WCpsKpgJSAS0mlqTtvameqggDwWEKQYDqrnTMYSbQBZFVPmYUoiCz1p1x DKt3zPTwEbUlM4pOIpoQNmf6EW1Idjof0uNEe4lmvrSF+y+mqhP6mm3JuxjEBK9P FWmJmwIDAQABo4IBEjCCAQ4wHQYDVR0OBBYEFGlEJwXcLu2l9IHE13hF50Rd+IdH MIHeBgNVHSMEgdYwgdOAFGlEJwXcLu2l9IHE13hF50Rd+IdHoYG3pIG0MIGxMQsw CQYDVQQGEwJVUzEXMBUGA1UECBMOTm9ydGggQ2Fyb2xpbmExEDAOBgNVBAcTB1Jh bGVpZ2gxFjAUBgNVBAoTDVJlZCBIYXQsIEluYy4xGDAWBgNVBAsTD1JlZCBIYXQg TmV0d29yazEiMCAGA1UEAxMZUkhOIENlcnRpZmljYXRlIEF1dGhvcml0eTEhMB8G CSqGSIb3DQEJARYScmhuLW5vY0ByZWRoYXQuY29tggEAMAwGA1UdEwQFMAMBAf8w DQYJKoZIhvcNAQEEBQADgYEAI8nKB59eljmD4E7a3UeEMMrU1TiG+d6Ig8osRyY2 q/QUHigp3n0QSl6RPlqZBwypLuP7eERJxTLW6HqX/ynQM64munYGfnmXFwxPLSqL iqxBWa7pxFUtuYjfm3tB+DIu7snAWeIwV143RynALXgz086jK9yE2r87Lku2s7ZO noA= -----END CERTIFICATE----- Download/Exception/DownloadError.php000064400000000417152325653710013556 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Download\Exception; defined('_JEXEC') or die; class DownloadError extends \RuntimeException { } Download/Download.php000064400000025762152325653710010620 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Download; use FOF30\Container\Container; use FOF30\Download\Exception\DownloadError; use JText; use FOF30\Timer\Timer; defined('_JEXEC') or die; class Download { /** * The component container object * * @var Container */ protected $container = null; /** * Parameters passed from the GUI when importing from URL * * @var array */ private $params = array(); /** * The download adapter which will be used by this class * * @var DownloadInterface */ private $adapter = null; /** * Additional params that will be passed to the adapter while performing the download * * @var array */ private $adapterOptions = array(); /** * Public constructor * * @param \FOF30\Container\Container $c The component container */ public function __construct(Container $c) { $this->container = $c; // Find the best fitting adapter $allAdapters = self::getFiles(__DIR__ . '/Adapter', array(), array('AbstractAdapter.php', 'cacert.pem')); $priority = 0; foreach ($allAdapters as $adapterInfo) { /** @var Adapter\AbstractAdapter $adapter */ $adapter = new $adapterInfo['classname']; if (!$adapter->isSupported()) { continue; } if ($adapter->priority > $priority) { $this->adapter = $adapter; $priority = $adapter->priority; } } // Load the language strings $c->platform->loadTranslations('lib_fof30'); } /** * Forces the use of a specific adapter * * @param string $className The name of the class or the name of the adapter */ public function setAdapter($className) { $adapter = null; if (class_exists($className, true)) { $adapter = new $className; } elseif (class_exists('\\FOF30\\Download\\Adapter\\' . ucfirst($className))) { $className = '\\FOF30\\Download\\Adapter\\' . ucfirst($className); $adapter = new $className; } if (is_object($adapter) && ($adapter instanceof DownloadInterface)) { $this->adapter = $adapter; } } /** * Returns the name of the current adapter * * @return string */ public function getAdapterName() { if(is_object($this->adapter)) { $class = get_class($this->adapter); return strtolower(str_ireplace('FOF30\\Download\\Adapter\\', '', $class)); } return ''; } /** * Sets the additional options for the adapter * * @param array $options * * @codeCoverageIgnore */ public function setAdapterOptions(array $options) { $this->adapterOptions = $options; } /** * Returns the additional options for the adapter * * @return array * * @codeCoverageIgnore */ public function getAdapterOptions() { return $this->adapterOptions; } /** * Used to decode the $params array * * @param string $key The parameter key you want to retrieve the value for * @param mixed $default The default value, if none is specified * * @return mixed The value for this parameter key */ private function getParam($key, $default = null) { if (array_key_exists($key, $this->params)) { return $this->params[$key]; } else { return $default; } } /** * Download data from a URL and return it. * * Important note about ranges: byte ranges start at 0. This means that the first 500 bytes of a file are from 0 * to 499, NOT from 1 to 500. If you ask more bytes than there are in the file or a range which is invalid or does * not exist this method will return false. * * @param string $url The URL to download from * @param int $from Byte range to start downloading from. Use null (default) for start of file. * @param int $to Byte range to stop downloading. Use null to download the entire file ($from will be ignored!) * * @return bool|string The downloaded data or false on failure */ public function getFromURL($url, $from = null, $to = null) { try { return $this->adapter->downloadAndReturn($url, $from, $to, $this->adapterOptions); } catch (DownloadError $e) { return false; } } /** * Performs the staggered download of file. * * @param array $params A parameters array, as sent by the user interface * * @return array A return status array */ public function importFromURL($params) { $this->params = $params; // Fetch data $url = $this->getParam('url'); $localFilename = $this->getParam('localFilename'); $frag = $this->getParam('frag', -1); $totalSize = $this->getParam('totalSize', -1); $doneSize = $this->getParam('doneSize', -1); $maxExecTime = $this->getParam('maxExecTime', 5); $runTimeBias = $this->getParam('runTimeBias', 75); $length = $this->getParam('length', 1048576); if (empty($localFilename)) { $localFilename = basename($url); if (strpos($localFilename, '?') !== false) { $paramsPos = strpos($localFilename, '?'); $localFilename = substr($localFilename, 0, $paramsPos - 1); $platformBaseDirectories = $this->container->platform->getPlatformBaseDirs(); $tmpDir = $platformBaseDirectories['tmp']; $tmpDir = rtrim($tmpDir, '/\\'); $localFilename = $tmpDir . '/' . $localFilename; } } // Init retArray $retArray = array( "status" => true, "error" => '', "frag" => $frag, "totalSize" => $totalSize, "doneSize" => $doneSize, "percent" => 0, "localfile" => $localFilename ); try { $timer = new Timer($maxExecTime, $runTimeBias); $start = $timer->getRunningTime(); // Mark the start of this download $break = false; // Don't break the step do { // Do we have to initialize the file? if ($frag == -1) { // Currently downloaded size $doneSize = 0; if (@file_exists($localFilename)) { @unlink($localFilename); } // Delete and touch the output file $fp = @fopen($localFilename, 'wb'); if ($fp !== false) { @fclose($fp); } // Init $frag = 0; $retArray['totalSize'] = $this->adapter->getFileSize($url); if ($retArray['totalSize'] <= 0) { $retArray['totalSize'] = 0; } $totalSize = $retArray['totalSize']; } // Calculate from and length $from = $frag * $length; $to = $length + $from - 1; // Try to download the first frag $required_time = 1.0; $error = ''; try { $result = $this->adapter->downloadAndReturn($url, $from, $to, $this->adapterOptions); } catch (DownloadError $e) { $result = false; $error = $e->getMessage(); } if ($result === false) { // Failed download if ($frag == 0) { // Failure to download first frag = failure to download. Period. $retArray['status'] = false; $retArray['error'] = $error; return $retArray; } else { // Since this is a staggered download, consider this normal and finish $frag = -1; $totalSize = $doneSize; $break = true; } } // Add the currently downloaded frag to the total size of downloaded files if ($result !== false) { $fileSize = strlen($result); $doneSize += $fileSize; // Append the file $fp = @fopen($localFilename, 'ab'); if ($fp === false) { // Can't open the file for writing $retArray['status'] = false; $retArray['error'] = JText::sprintf('LIB_FOF_DOWNLOAD_ERR_COULDNOTWRITELOCALFILE', $localFilename); return $retArray; } fwrite($fp, $result); fclose($fp); $frag++; if (($fileSize < $length) || ($fileSize > $length) || (($totalSize == $doneSize) && ($totalSize > 0)) ) { // A partial download or a download larger than the frag size means we are done $frag = -1; //debugMsg("-- Import complete (partial download of last frag)"); $totalSize = $doneSize; $break = true; } } // Advance the frag pointer and mark the end $end = $timer->getRunningTime(); // Do we predict that we have enough time? $required_time = max(1.1 * ($end - $start), $required_time); if ($required_time > (10 - $end + $start)) { $break = true; } $start = $end; } while (($timer->getTimeLeft() > 0) && !$break); if ($frag == -1) { $percent = 100; } elseif ($doneSize <= 0) { $percent = 0; } else { if ($totalSize > 0) { $percent = 100 * ($doneSize / $totalSize); } else { $percent = 0; } } // Update $retArray $retArray = array( "status" => true, "error" => '', "frag" => $frag, "totalSize" => $totalSize, "doneSize" => $doneSize, "percent" => $percent, ); } catch (DownloadError $e) { $retArray['status'] = false; $retArray['error'] = $e->getMessage(); } return $retArray; } /** * This method will crawl a starting directory and get all the valid files * that will be analyzed by __construct. Then it organizes them into an * associative array. * * @param string $path Folder where we should start looking * @param array $ignoreFolders Folder ignore list * @param array $ignoreFiles File ignore list * * @return array Associative array, where the `fullpath` key contains the path to the file, * and the `classname` key contains the name of the class */ protected static function getFiles($path, array $ignoreFolders = array(), array $ignoreFiles = array()) { $return = array(); $files = self::scanDirectory($path, $ignoreFolders, $ignoreFiles); // Ok, I got the files, now I have to organize them foreach ($files as $file) { $clean = str_replace($path, '', $file); $clean = trim(str_replace('\\', '/', $clean), '/'); $parts = explode('/', $clean); $return[] = array( 'fullpath' => $file, 'classname' => '\\FOF30\\Download\\Adapter\\' . ucfirst(basename($parts[0], '.php')) ); } return $return; } /** * Recursive function that will scan every directory unless it's in the * ignore list. Files that aren't in the ignore list are returned. * * @param string $path Folder where we should start looking * @param array $ignoreFolders Folder ignore list * @param array $ignoreFiles File ignore list * * @return array List of all the files */ protected static function scanDirectory($path, array $ignoreFolders = array(), array $ignoreFiles = array()) { $return = array(); $handle = @opendir($path); if (!$handle) { return $return; } while (($file = readdir($handle)) !== false) { if ($file == '.' || $file == '..') { continue; } $fullpath = $path . '/' . $file; if ((is_dir($fullpath) && in_array($file, $ignoreFolders)) || (is_file($fullpath) && in_array($file, $ignoreFiles))) { continue; } if (is_dir($fullpath)) { $return = array_merge(self::scanDirectory($fullpath, $ignoreFolders, $ignoreFiles), $return); } else { $return[] = $path . '/' . $file; } } return $return; } } Download/DownloadInterface.php000064400000005066152325653710012434 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Download; use FOF30\Download\Exception\DownloadError; defined('_JEXEC') or die; /** * Interface DownloadInterface * * @codeCoverageIgnore */ interface DownloadInterface { /** * Does this download adapter support downloading files in chunks? * * @return boolean True if chunk download is supported */ public function supportsChunkDownload(); /** * Does this download adapter support reading the size of a remote file? * * @return boolean True if remote file size determination is supported */ public function supportsFileSize(); /** * Is this download class supported in the current server environment? * * @return boolean True if this server environment supports this download class */ public function isSupported(); /** * Get the priority of this adapter. If multiple download adapters are * supported on a site, the one with the highest priority will be * used. * * @return boolean */ public function getPriority(); /** * Returns the name of this download adapter in use * * @return string */ public function getName(); /** * Download a part (or the whole) of a remote URL and return the downloaded * data. You are supposed to check the size of the returned data. If it's * smaller than what you expected you've reached end of file. If it's empty * you have tried reading past EOF. If it's larger than what you expected * the server doesn't support chunk downloads. * * If this class' supportsChunkDownload returns false you should assume * that the $from and $to parameters will be ignored. * * @param string $url The remote file's URL * @param integer $from Byte range to start downloading from. Use null for start of file. * @param integer $to Byte range to stop downloading. Use null to download the entire file ($from is ignored) * @param array $params Additional params that will be added before performing the download * * @return string The raw file data retrieved from the remote URL. * * @throws DownloadError A generic exception is thrown on error */ public function downloadAndReturn($url, $from = null, $to = null, array $params = array()); /** * Get the size of a remote file in bytes * * @param string $url The remote file's URL * * @return integer The file size, or -1 if the remote server doesn't support this feature */ public function getFileSize($url); } Encrypt/AesAdapter/AbstractAdapter.php000064400000003470152325653710013773 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Encrypt\AesAdapter; // Protect from unauthorized access defined('_JEXEC') or die(); /** * Abstract AES encryption class */ abstract class AbstractAdapter { /** * Trims or zero-pads a key / IV * * @param string $key The key or IV to treat * @param int $size The block size of the currently used algorithm * * @return null|string Null if $key is null, treated string of $size byte length otherwise */ public function resizeKey($key, $size) { if (empty($key)) { return null; } $keyLength = strlen($key); if (function_exists('mb_strlen')) { $keyLength = mb_strlen($key, 'ASCII'); } if ($keyLength == $size) { return $key; } if ($keyLength > $size) { if (function_exists('mb_substr')) { return mb_substr($key, 0, $size, 'ASCII'); } return substr($key, 0, $size); } return $key . str_repeat("\0", ($size - $keyLength)); } /** * Returns null bytes to append to the string so that it's zero padded to the specified block size * * @param string $string The binary string which will be zero padded * @param int $blockSize The block size * * @return string The zero bytes to append to the string to zero pad it to $blockSize */ protected function getZeroPadding($string, $blockSize) { $stringSize = strlen($string); if (function_exists('mb_strlen')) { $stringSize = mb_strlen($string, 'ASCII'); } if ($stringSize == $blockSize) { return ''; } if ($stringSize < $blockSize) { return str_repeat("\0", $blockSize - $stringSize); } $paddingBytes = $stringSize % $blockSize; return str_repeat("\0", $blockSize - $paddingBytes); } } Encrypt/AesAdapter/AdapterInterface.php000064400000006126152325653710014131 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Encrypt\AesAdapter; // Protect from unauthorized access use FOF30\Utils\Phpfunc; defined('_JEXEC') or die(); /** * Interface for AES encryption adapters */ interface AdapterInterface { /** * Sets the AES encryption mode. * * WARNING: The strength is deprecated as it has a different effect in MCrypt and OpenSSL. MCrypt was abandoned in * 2003 before the Rijndael-128 algorithm was officially the Advanced Encryption Standard (AES). MCrypt also offered * Rijndael-192 and Rijndael-256 algorithms with different block sizes. These are NOT used in AES. OpenSSL, however, * implements AES correctly. It always uses a 128-bit (16 byte) block. The 192 and 256 bit strengths refer to the * key size, not the block size. Therefore using different strengths in MCrypt and OpenSSL will result in different * and incompatible ciphertexts. * * TL;DR: Always use $strength = 128! * * @param string $mode Choose between CBC (recommended) or ECB * @param int $strength Bit strength of the key (128, 192 or 256 bits). DEPRECATED. READ NOTES ABOVE. * * @return mixed */ public function setEncryptionMode($mode = 'cbc', $strength = 128); /** * Encrypts a string. Returns the raw binary ciphertext. * * WARNING: The plaintext is zero-padded to the algorithm's block size. You are advised to store the size of the * plaintext and trim the string to that length upon decryption. * * @param string $plainText The plaintext to encrypt * @param string $key The raw binary key (will be zero-padded or chopped if its size is different than the block size) * @param null|string $iv The initialization vector (for CBC mode algorithms) * * @return string The raw encrypted binary string. */ public function encrypt($plainText, $key, $iv = null); /** * Decrypts a string. Returns the raw binary plaintext. * * $ciphertext MUST start with the IV followed by the ciphertext, even for EBC data (the first block of data is * dropped in EBC mode since there is no concept of IV in EBC). * * WARNING: The returned plaintext is zero-padded to the algorithm's block size during encryption. You are advised * to trim the string to the original plaintext's length upon decryption. While rtrim($decrypted, "\0") sounds * appealing it's NOT the correct approach for binary data (zero bytes may actually be part of your plaintext, not * just padding!). * * @param string $cipherText The ciphertext to encrypt * @param string $key The raw binary key (will be zero-padded or chopped if its size is different than the block size) * * @return string The raw unencrypted binary string. */ public function decrypt($cipherText, $key); /** * Returns the encryption block size in bytes * * @return int */ public function getBlockSize(); /** * Is this adapter supported? * * @return bool */ public function isSupported(Phpfunc $phpfunc = null); } Encrypt/AesAdapter/Mcrypt.php000064400000006015152325653710012203 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Encrypt\AesAdapter; // Protect from unauthorized access use FOF30\Encrypt\Randval; use FOF30\Utils\Phpfunc; defined('_JEXEC') or die(); class Mcrypt extends AbstractAdapter implements AdapterInterface { protected $cipherType = MCRYPT_RIJNDAEL_128; protected $cipherMode = MCRYPT_MODE_CBC; public function setEncryptionMode($mode = 'cbc', $strength = 128) { switch ((int) $strength) { default: case '128': $this->cipherType = MCRYPT_RIJNDAEL_128; break; case '192': $this->cipherType = MCRYPT_RIJNDAEL_192; break; case '256': $this->cipherType = MCRYPT_RIJNDAEL_256; break; } switch (strtolower($mode)) { case 'ecb': $this->cipherMode = MCRYPT_MODE_ECB; break; default: case 'cbc': $this->cipherMode = MCRYPT_MODE_CBC; break; } } public function encrypt($plainText, $key, $iv = null) { $iv_size = $this->getBlockSize(); $key = $this->resizeKey($key, $iv_size); $iv = $this->resizeKey($iv, $iv_size); if (empty($iv)) { $randVal = new Randval(); $iv = $randVal->generate($iv_size); } $cipherText = mcrypt_encrypt($this->cipherType, $key, $plainText, $this->cipherMode, $iv); $cipherText = $iv . $cipherText; return $cipherText; } public function decrypt($cipherText, $key) { $iv_size = $this->getBlockSize(); $key = $this->resizeKey($key, $iv_size); $iv = substr($cipherText, 0, $iv_size); $cipherText = substr($cipherText, $iv_size); $plainText = mcrypt_decrypt($this->cipherType, $key, $cipherText, $this->cipherMode, $iv); return $plainText; } public function isSupported(Phpfunc $phpfunc = null) { if (!is_object($phpfunc) || !($phpfunc instanceof $phpfunc)) { $phpfunc = new Phpfunc(); } if (!$phpfunc->function_exists('mcrypt_get_key_size')) { return false; } if (!$phpfunc->function_exists('mcrypt_get_iv_size')) { return false; } if (!$phpfunc->function_exists('mcrypt_create_iv')) { return false; } if (!$phpfunc->function_exists('mcrypt_encrypt')) { return false; } if (!$phpfunc->function_exists('mcrypt_decrypt')) { return false; } if (!$phpfunc->function_exists('mcrypt_list_algorithms')) { return false; } if (!$phpfunc->function_exists('hash')) { return false; } if (!$phpfunc->function_exists('hash_algos')) { return false; } $algorightms = $phpfunc->mcrypt_list_algorithms(); if (!in_array('rijndael-128', $algorightms)) { return false; } if (!in_array('rijndael-192', $algorightms)) { return false; } if (!in_array('rijndael-256', $algorightms)) { return false; } $algorightms = $phpfunc->hash_algos(); if (!in_array('sha256', $algorightms)) { return false; } return true; } public function getBlockSize() { return mcrypt_get_iv_size($this->cipherType, $this->cipherMode); } } Encrypt/AesAdapter/OpenSSL.php000064400000010247152325653710012212 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Encrypt\AesAdapter; // Protect from unauthorized access use FOF30\Encrypt\Randval; use FOF30\Utils\Phpfunc; defined('_JEXEC') or die(); class OpenSSL extends AbstractAdapter implements AdapterInterface { /** * The OpenSSL options for encryption / decryption * * PHP 5.3 does not have the constants OPENSSL_RAW_DATA and OPENSSL_ZERO_PADDING. In fact, the parameter * is called $raw_data and is a boolean. Since integer 1 is equivalent to boolean TRUE in PHP we can get * away with initializing this parameter with the integer 1. * * @var int */ protected $openSSLOptions = 1; /** * The encryption method to use * * @var string */ protected $method = 'aes-128-cbc'; public function __construct() { /** * PHP 5.4 and later replaced the $raw_data parameter with the $options parameter. Instead of a boolean we need * to pass some flags. Here you go. * * Since PHP 5.3 does NOT have the relevant constants we must NOT run this bit of code under PHP 5.3. * * See http://stackoverflow.com/questions/24707007/using-openssl-raw-data-param-in-openssl-decrypt-with-php-5-3#24707117 */ if (version_compare(PHP_VERSION, '5.4.0', 'ge')) { $this->openSSLOptions = OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING; } } public function setEncryptionMode($mode = 'cbc', $strength = 128) { static $availableAlgorithms = null; static $defaultAlgo = 'aes-128-cbc'; if (!is_array($availableAlgorithms)) { $availableAlgorithms = openssl_get_cipher_methods(); foreach (array('aes-256-cbc', 'aes-256-ecb', 'aes-192-cbc', 'aes-192-ecb', 'aes-128-cbc', 'aes-128-ecb') as $algo) { if (in_array($algo, $availableAlgorithms)) { $defaultAlgo = $algo; break; } } } $strength = (int) $strength; $mode = strtolower($mode); if (!in_array($strength, array(128, 192, 256))) { $strength = 256; } if (!in_array($mode, array('cbc', 'ebc'))) { $mode = 'cbc'; } $algo = 'aes-' . $strength . '-' . $mode; if (!in_array($algo, $availableAlgorithms)) { $algo = $defaultAlgo; } $this->method = $algo; } public function encrypt($plainText, $key, $iv = null) { $iv_size = $this->getBlockSize(); $key = $this->resizeKey($key, $iv_size); $iv = $this->resizeKey($iv, $iv_size); if (empty($iv)) { $randVal = new Randval(); $iv = $randVal->generate($iv_size); } $plainText .= $this->getZeroPadding($plainText, $iv_size); $cipherText = openssl_encrypt($plainText, $this->method, $key, $this->openSSLOptions, $iv); $cipherText = $iv . $cipherText; return $cipherText; } public function decrypt($cipherText, $key) { $iv_size = $this->getBlockSize(); $key = $this->resizeKey($key, $iv_size); $iv = substr($cipherText, 0, $iv_size); $cipherText = substr($cipherText, $iv_size); $plainText = openssl_decrypt($cipherText, $this->method, $key, $this->openSSLOptions, $iv); return $plainText; } public function isSupported(Phpfunc $phpfunc = null) { if (!is_object($phpfunc) || !($phpfunc instanceof $phpfunc)) { $phpfunc = new Phpfunc(); } if (!$phpfunc->function_exists('openssl_get_cipher_methods')) { return false; } if (!$phpfunc->function_exists('openssl_random_pseudo_bytes')) { return false; } if (!$phpfunc->function_exists('openssl_cipher_iv_length')) { return false; } if (!$phpfunc->function_exists('openssl_encrypt')) { return false; } if (!$phpfunc->function_exists('openssl_decrypt')) { return false; } if (!$phpfunc->function_exists('hash')) { return false; } if (!$phpfunc->function_exists('hash_algos')) { return false; } $algorightms = $phpfunc->openssl_get_cipher_methods(); if (!in_array('aes-128-cbc', $algorightms)) { return false; } $algorightms = $phpfunc->hash_algos(); if (!in_array('sha256', $algorightms)) { return false; } return true; } /** * @return int */ public function getBlockSize() { return openssl_cipher_iv_length($this->method); } } Encrypt/Aes.php000064400000016245152325653710007432 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Encrypt; use FOF30\Encrypt\AesAdapter\AdapterInterface; use FOF30\Encrypt\AesAdapter\Mcrypt; use FOF30\Encrypt\AesAdapter\OpenSSL; use FOF30\Utils\Phpfunc; defined('_JEXEC') or die; /** * A simple abstraction to AES encryption * * Usage: * * // Create a new instance. The key is ignored – only use it if you have legacy encrypted content you need to decrypt * $aes = new Aes('ignored'); * // Set the password. Do not use uf you have legacy encrypted content you need to decrypt * $aes->setPassword('yourRealPassword'); * // Encrypt something. * $cipherText = $aes->encryptString($sourcePlainText); * // Decypt something * $plainText = $aes->decryptString($sourceCipherText); */ class Aes { /** * The cipher key. * * @var string */ private $key = ''; /** * The AES encryption adapter in use. * * @var AdapterInterface */ private $adapter; /** * Initialise the AES encryption object. * * Note: If the key is not 16 bytes this class will do a stupid key expansion for legacy reasons (produce the * SHA-256 of the key string and throw away half of it). * * @param string $key The encryption key (password). It can be a raw key (16 bytes) or a passphrase. * @param int $strength Bit strength (128, 192 or 256) – ALWAYS USE 128 BITS. THIS PARAMETER IS DEPRECATED. * @param string $mode Encryption mode. Can be ebc or cbc. We recommend using cbc. * @param Phpfunc $phpfunc For testing */ public function __construct($key, $strength = 128, $mode = 'cbc', Phpfunc $phpfunc = null) { $this->adapter = new OpenSSL(); if (!$this->adapter->isSupported($phpfunc)) { $this->adapter = new Mcrypt(); } $this->adapter->setEncryptionMode($mode, $strength); $this->setPassword($key, true); } /** * Sets the password for this instance. * * WARNING: Do not use the legacy mode, it's insecure * * @param string $password The password (either user-provided password or binary encryption key) to use * @param bool $legacyMode True to use the legacy key expansion. We recommend against using it. */ public function setPassword($password, $legacyMode = false) { $this->key = $password; $passLength = strlen($password); if (function_exists('mb_strlen')) { $passLength = mb_strlen($password, 'ASCII'); } // Legacy mode was doing something stupid, requiring a key of 32 bytes. DO NOT USE LEGACY MODE! if ($legacyMode && ($passLength != 32)) { // Legacy mode: use the sha256 of the password $this->key = hash('sha256', $password, true); // We have to trim or zero pad the password (we end up throwing half of it away in Rijndael-128 / AES...) $this->key = $this->adapter->resizeKey($this->key, $this->adapter->getBlockSize()); } } /** * Encrypts a string using AES * * @param string $stringToEncrypt The plaintext to encrypt * @param bool $base64encoded Should I Base64-encode the result? * * @return string The cryptotext. Please note that the first 16 bytes of * the raw string is the IV (initialisation vector) which * is necessary for decoding the string. */ public function encryptString($stringToEncrypt, $base64encoded = true) { $blockSize = $this->adapter->getBlockSize(); $randVal = new Randval(); $iv = $randVal->generate($blockSize); $key = $this->getExpandedKey($blockSize, $iv); $cipherText = $this->adapter->encrypt($stringToEncrypt, $key, $iv); // Optionally pass the result through Base64 encoding if ($base64encoded) { $cipherText = base64_encode($cipherText); } // Return the result return $cipherText; } /** * Decrypts a ciphertext into a plaintext string using AES * * @param string $stringToDecrypt The ciphertext to decrypt. The first 16 bytes of the raw string must contain * the IV (initialisation vector). * @param bool $base64encoded Should I Base64-decode the data before decryption? * * @return string The plain text string */ public function decryptString($stringToDecrypt, $base64encoded = true) { if ($base64encoded) { $stringToDecrypt = base64_decode($stringToDecrypt); } // Extract IV $iv_size = $this->adapter->getBlockSize(); $iv = substr($stringToDecrypt, 0, $iv_size); $key = $this->getExpandedKey($iv_size, $iv); // Decrypt the data $plainText = $this->adapter->decrypt($stringToDecrypt, $key); return $plainText; } /** * Is AES encryption supported by this PHP installation? * * @return boolean */ public static function isSupported(Phpfunc $phpfunc = null) { if (!is_object($phpfunc) || !($phpfunc instanceof $phpfunc)) { $phpfunc = new Phpfunc(); } $adapter = new OpenSSL(); if (!$adapter->isSupported($phpfunc)) { $adapter = new Mcrypt(); } if (!$adapter->isSupported($phpfunc)) { return false; } if (!$phpfunc->function_exists('base64_encode')) { return false; } if (!$phpfunc->function_exists('base64_decode')) { return false; } if (!$phpfunc->function_exists('hash_algos')) { return false; } $algorightms = $phpfunc->hash_algos(); if (!in_array('sha256', $algorightms)) { return false; } return true; } /** * @param $blockSize * @param $iv * * @return string */ public function getExpandedKey($blockSize, $iv) { $key = $this->key; $passLength = strlen($key); if (function_exists('mb_strlen')) { $passLength = mb_strlen($key, 'ASCII'); } if ($passLength != $blockSize) { $iterations = 1000; $salt = $this->adapter->resizeKey($iv, 16); $key = hash_pbkdf2('sha256', $this->key, $salt, $iterations, $blockSize, true); } return $key; } } if (!function_exists('hash_pbkdf2')) { function hash_pbkdf2($algo, $password, $salt, $count, $length = 0, $raw_output = false) { if (!in_array(strtolower($algo), hash_algos())) { trigger_error(__FUNCTION__ . '(): Unknown hashing algorithm: ' . $algo, E_USER_WARNING); } if (!is_numeric($count)) { trigger_error(__FUNCTION__ . '(): expects parameter 4 to be long, ' . gettype($count) . ' given', E_USER_WARNING); } if (!is_numeric($length)) { trigger_error(__FUNCTION__ . '(): expects parameter 5 to be long, ' . gettype($length) . ' given', E_USER_WARNING); } if ($count <= 0) { trigger_error(__FUNCTION__ . '(): Iterations must be a positive integer: ' . $count, E_USER_WARNING); } if ($length < 0) { trigger_error(__FUNCTION__ . '(): Length must be greater than or equal to 0: ' . $length, E_USER_WARNING); } $output = ''; $block_count = $length ? ceil($length / strlen(hash($algo, '', $raw_output))) : 1; for ($i = 1; $i <= $block_count; $i++) { $last = $xorsum = hash_hmac($algo, $salt . pack('N', $i), $password, true); for ($j = 1; $j < $count; $j++) { $xorsum ^= ($last = hash_hmac($algo, $last, $password, true)); } $output .= $xorsum; } if (!$raw_output) { $output = bin2hex($output); } return $length ? substr($output, 0, $length) : $output; } } Encrypt/Base32.php000064400000010730152325653710007732 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Encrypt; defined('_JEXEC') or die; /** * Base32 encoding class, used by the TOTP */ class Base32 { /** * CSRFC3548 * * The character set as defined by RFC3548 * @link http://www.ietf.org/rfc/rfc3548.txt */ const CSRFC3548 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; /** * Converts any ascii string to a binary string * * @param string $str The string you want to convert * * @return string String of 0's and 1's */ private function str2bin($str) { $chrs = unpack('C*', $str); return vsprintf(str_repeat('%08b', count($chrs)), $chrs); } /** * Converts a binary string to an ascii string * * @param string $str The string of 0's and 1's you want to convert * * @return string The ascii output * * @throws \InvalidArgumentException */ private function bin2str($str) { if (strlen($str) % 8 > 0) { throw new \InvalidArgumentException('Length must be divisible by 8'); } if (!preg_match('/^[01]+$/', $str)) { throw new \InvalidArgumentException('Only 0\'s and 1\'s are permitted'); } preg_match_all('/.{8}/', $str, $chrs); $chrs = array_map('bindec', $chrs[0]); // I'm just being slack here array_unshift($chrs, 'C*'); return call_user_func_array('pack', $chrs); } /** * Converts a correct binary string to base32 * * @param string $str The string of 0's and 1's you want to convert * * @return string String encoded as base32 * * @throws \InvalidArgumentException */ private function fromBin($str) { if (strlen($str) % 8 > 0) { throw new \InvalidArgumentException('Length must be divisible by 8'); } if (!preg_match('/^[01]+$/', $str)) { throw new \InvalidArgumentException('Only 0\'s and 1\'s are permitted'); } // Base32 works on the first 5 bits of a byte, so we insert blanks to pad it out $str = preg_replace('/(.{5})/', '000$1', $str); // We need a string divisible by 5 $length = strlen($str); $rbits = $length & 7; if ($rbits > 0) { // Excessive bits need to be padded $ebits = substr($str, $length - $rbits); $str = substr($str, 0, $length - $rbits); $str .= "000$ebits" . str_repeat('0', 5 - strlen($ebits)); } preg_match_all('/.{8}/', $str, $chrs); $chrs = array_map(array($this, 'mapCharset'), $chrs[0]); return join('', $chrs); } /** * Accepts a base32 string and returns an ascii binary string * * @param string $str The base32 string to convert * * @return string Ascii binary string * * @throws \InvalidArgumentException */ private function toBin($str) { if (!preg_match('/^[' . self::CSRFC3548 . ']+$/', $str)) { throw new \InvalidArgumentException('Base64 string must match character set'); } // Convert the base32 string back to a binary string $str = join('', array_map(array($this, 'mapBin'), str_split($str))); // Remove the extra 0's we added $str = preg_replace('/000(.{5})/', '$1', $str); // Unpad if nessicary $length = strlen($str); $rbits = $length & 7; if ($rbits > 0) { $str = substr($str, 0, $length - $rbits); } return $str; } /** * Convert any string to a base32 string * This should be binary safe... * * @param string $str The string to convert * * @return string The converted base32 string */ public function encode($str) { return $this->fromBin($this->str2bin($str)); } /** * Convert any base32 string to a normal sctring * This should be binary safe... * * @param string $str The base32 string to convert * * @return string The normal string */ public function decode($str) { $str = strtoupper($str); return $this->bin2str($this->tobin($str)); } /** * Used with array_map to map the bits from a binary string * directly into a base32 character set * * @param string $str The string of 0's and 1's you want to convert * * @return string Resulting base32 character * * @access private */ private function mapCharset($str) { // Huh! $x = self::CSRFC3548; return $x[bindec($str)]; } /** * Used with array_map to map the characters from a base32 * character set directly into a binary string * * @param string $chr The caracter to map * * @return string String of 0's and 1's * * @access private */ private function mapBin($chr) { return sprintf('%08b', strpos(self::CSRFC3548, $chr)); } } Encrypt/EncryptService.php000064400000016330152325653710011662 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Encrypt; use FOF30\Container\Container; /** * Data encryption service for FOF-based components. * * This service allows you to transparently encrypt and decrypt *text* plaintext data. Use it to provide encryption for * sensitive or personal data stored in your database. Please remember: * * - The default behavior is to create a file with a random key on your component's root. If the file cannot be created * the encryption is turned off. * - The key file is only created when you access the service. If you never use this service nothing happens (for * backwards compatibility). * - You have to manually encrypt and decrypt data. It won't happen magically. * - Encrypted data cannot be searched unless you implement your own, slow, search algorithm. * - Data encryption is meant to be used on top of, not instead of, any other security measures for your site. * - Data encryption only protects against exploits targeting the database. If the attacker *also* gains read access to * your filesystem OR if the attacker gains read / write access to the filesystem the encryption won't protect you. * This is a full compromise of your site. At this point you're pwned and nothing can protect you. If you don't * understand this simple truth do NOT use encryption. * - This is meant as a simple and basic encryption layer. It has not been independently verified. Use at your own risk. * * This service has the following FOF application configuration parameters which can be declared under the "container" * key (e.g. the "name" attribute of the fof.xml elements under fof > common > container > option): * * - encrypt_key_file The path to the key file, relative to the component's backend root and WITHOUT the .php extension * - encrypt_key_const The constant for the key. By default it is COMPONENTNAME_FOF_ENCRYPT_SERVICE_SECRETKEY where * COMPONENTNAME corresponds to the uppercased com_componentname without the com_ prefix. * * @package FOF30\Encrypt * * @since 3.3.2 */ class EncryptService { /** * The component's container * * @var Container * @since 3.3.2 */ private $container; /** * The encryption engine used by this service * * @var Aes * @since 3.3.2 */ private $aes; /** * EncryptService constructor. * * @param Container $c The FOF component container * * @since 3.3.2 */ public function __construct(Container $c) { $this->container = $c; $this->initialize(); } /** * Encrypt the plaintext $data and return the ciphertext prefixed by ###AES128### * * @param string $data The plaintext data * * @return string The ciphertext, prefixed by ###AES128### * * @since 3.3.2 */ public function encrypt($data) { if (!is_object($this->aes)) { return $data; } $encrypted = $this->aes->encryptString($data, true); return '###AES128###' . $encrypted; } /** * Decrypt the ciphertext, prefixed by ###AES128###, and return the plaintext. * * @param string $data The ciphertext, prefixed by ###AES128### * * @return string The plaintext data * * @since 3.3.2 */ public function decrypt($data) { if (substr($data, 0, 12) != '###AES128###') { return $data; } $data = substr($data, 12); if (!is_object($this->aes)) { return $data; } $decrypted = $this->aes->decryptString($data, true); // Decrypted data is null byte padded. We have to remove the padding before proceeding. return rtrim($decrypted, "\0"); } /** * Initialize the AES cryptography object * * @since 3.3.2 * * @return void */ private function initialize() { if (is_object($this->aes)) { return; } $password = $this->getPassword(); if (empty($password)) { return; } $phpFunc = new \FOF30\Utils\Phpfunc(); $this->aes = new Aes($password, 128, 'cbc', $phpFunc); } /** * Returns the path to the secret key file * * @return string * * @since 3.3.2 */ private function getPasswordFilePath() { $default = 'encrypt_service_key'; $baseName = $this->container->appConfig->get('container.encrypt_key_file', $default); $baseName = trim($baseName, '/\\'); return $this->container->backEndPath . '/' . $baseName . '.php'; } /** * Get the name of the constant where the secret key is stored. Remember that this is searched first, before a new * key file is created. You can define this constant anywhere in your code loaded before the encryption service is * first used to prevent a key file being created. * * @return string * * @since 3.3.2 */ private function getConstantName() { $default = strtoupper($this->container->bareComponentName) . '_FOF_ENCRYPT_SERVICE_SECRETKEY'; return $this->container->appConfig->get('container.encrypt_key_const', $default); } /** * Returns the password used to encrypt information in Akeeba Susbcriptions * * @return string * * @since 3.3.2 */ private function getPassword() { $constantName = $this->getConstantName(); // If we have already read the file just return the key if (defined($constantName)) { return constant($constantName); } // Do I have a secret key file? $filePath = $this->getPasswordFilePath(); // I can't get the path to the file. Cut our losses and assume we can get no key. if (empty($filePath)) { define($constantName, ''); return ''; } // If not, try to create one. if (!file_exists($filePath)) { $this->makePasswordFile(); } // We failed to create a new file? Cut our losses and assume we can get no key. if (!file_exists($filePath) || !is_readable($filePath)) { define($constantName, ''); return ''; } // Try to include the key file include_once $filePath; // The key file contains garbage. Treason! Cut our losses and assume we can get no key. if (!defined($constantName)) { define($constantName, ''); return ''; } // Finally, return the key which was defined in the file (happy path). return constant($constantName); } /** * Create a new secret key file using a long, randomly generated password. The password generator uses a crypto-safe * pseudorandom number generator (PRNG) to ensure suitability of the password for encrypting data at rest. * * @return void * * @since 3.3.2 */ private function makePasswordFile() { // Get the path to the new secret key file. $filePath = $this->getPasswordFilePath(); // I can't get the path to the file. Sorry. if (empty($filePath)) { return; } $phpFunc = new \FOF30\Utils\Phpfunc(); $randval = new Randval($phpFunc); $secretKey = $randval->getRandomPassword(64); $constantName = $this->getConstantName(); $fileContent = "<?" . 'ph' . "p\n\n"; $fileContent .= <<< END defined('_JEXEC') or die; /** * This file is automatically generated. It contains a secret key used for encrypting data by the component. Please do * not remove, edit or manually replace this file. It will render your existing encrypted data unreadable forever. */ define('$constantName', '$secretKey'); END; $this->container->filesystem->fileWrite($filePath, $fileContent); } }Encrypt/Randval.php000064400000012272152325653710010305 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Encrypt; // Protect from unauthorized access use FOF30\Utils\Phpfunc; defined('_JEXEC') or die(); /** * Generates cryptographically-secure random values. */ class Randval implements RandvalInterface { /** * @var Phpfunc */ protected $phpfunc; /** * * Constructor. * * @param Phpfunc $phpfunc An object to intercept PHP function calls; * this makes testing easier. * */ public function __construct(Phpfunc $phpfunc = null) { if (!is_object($phpfunc) || !($phpfunc instanceof Phpfunc)) { $phpfunc = new Phpfunc(); } $this->phpfunc = $phpfunc; } /** * * Returns a cryptographically secure random value. * * @param integer $bytes How many bytes to return * * @return string */ public function generate($bytes = 32) { if ($this->phpfunc->extension_loaded('openssl') && (version_compare(PHP_VERSION, '5.3.4') >= 0 || IS_WIN)) { $strong = false; $randBytes = openssl_random_pseudo_bytes($bytes, $strong); if ($strong) { return $randBytes; } } if ($this->phpfunc->extension_loaded('mcrypt')) { return $this->phpfunc->mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM); } return $this->genRandomBytes($bytes); } /** * Generate random bytes. Adapted from Joomla! 3.2. * * @param integer $length Length of the random data to generate * * @return string Random binary data */ public function genRandomBytes($length = 32) { $length = (int) $length; $sslStr = ''; /* * Collect any entropy available in the system along with a number * of time measurements of operating system randomness. */ $bitsPerRound = 2; $maxTimeMicro = 400; $shaHashLength = 20; $randomStr = ''; $total = $length; // Check if we can use /dev/urandom. $urandom = false; $handle = null; // This is PHP 5.3.3 and up if ($this->phpfunc->function_exists('stream_set_read_buffer') && @is_readable('/dev/urandom')) { $handle = @fopen('/dev/urandom', 'rb'); if ($handle) { $urandom = true; } } while ($length > strlen($randomStr)) { $bytes = ($total > $shaHashLength)? $shaHashLength : $total; $total -= $bytes; /* * Collect any entropy available from the PHP system and filesystem. * If we have ssl data that isn't strong, we use it once. */ $entropy = rand() . uniqid(mt_rand(), true) . $sslStr; $entropy .= implode('', @fstat(fopen(__FILE__, 'r'))); $entropy .= memory_get_usage(); $sslStr = ''; if ($urandom) { stream_set_read_buffer($handle, 0); $entropy .= @fread($handle, $bytes); } else { /* * There is no external source of entropy so we repeat calls * to mt_rand until we are assured there's real randomness in * the result. * * Measure the time that the operations will take on average. */ $samples = 3; $duration = 0; for ($pass = 0; $pass < $samples; ++$pass) { $microStart = microtime(true) * 1000000; $hash = sha1(mt_rand(), true); for ($count = 0; $count < 50; ++$count) { $hash = sha1($hash, true); } $microEnd = microtime(true) * 1000000; $entropy .= $microStart . $microEnd; if ($microStart >= $microEnd) { $microEnd += 1000000; } $duration += $microEnd - $microStart; } $duration = $duration / $samples; /* * Based on the average time, determine the total rounds so that * the total running time is bounded to a reasonable number. */ $rounds = (int) (($maxTimeMicro / $duration) * 50); /* * Take additional measurements. On average we can expect * at least $bitsPerRound bits of entropy from each measurement. */ $iter = $bytes * (int) ceil(8 / $bitsPerRound); for ($pass = 0; $pass < $iter; ++$pass) { $microStart = microtime(true); $hash = sha1(mt_rand(), true); for ($count = 0; $count < $rounds; ++$count) { $hash = sha1($hash, true); } $entropy .= $microStart . microtime(true); } } $randomStr .= sha1($entropy, true); } if ($urandom) { @fclose($handle); } return substr($randomStr, 0, $length); } /** * Return a randomly generated password using safe characters (a-z, A-Z, 0-9). * * @param int $length How many characters long should the password be. Default is 64. * * @return string * * @since 3.3.2 */ public function getRandomPassword($length = 64) { $salt = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; $base = strlen($salt); $makepass = ''; /* * Start with a cryptographic strength random string, then convert it to * a string with the numeric base of the salt. * Shift the base conversion on each character so the character * distribution is even, and randomize the start shift so it's not * predictable. */ $random = $this->generate($length + 1); $shift = ord($random[0]); for ($i = 1; $i <= $length; ++$i) { $makepass .= $salt[($shift + ord($random[$i])) % $base]; $shift += ord($random[$i]); } return $makepass; } } Encrypt/RandvalInterface.php000064400000000621152325653710012121 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Encrypt; // Protect from unauthorized access defined('_JEXEC') or die(); interface RandvalInterface { /** * * Returns a cryptographically secure random value. * * @return string * */ public function generate(); } Encrypt/Totp.php000064400000011327152325653710007644 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Encrypt; defined('_JEXEC') or die; class Totp { /** * @var int The length of the resulting passcode (default: 6 digits) */ private $passCodeLength = 6; /** * @var number The PIN modulo. It is set automatically to log10(passCodeLength) */ private $pinModulo; /** * The length of the secret key, in characters (default: 10) * * @var int */ private $secretLength = 10; /** * The time step between successive TOTPs in seconds (default: 30 seconds) * * @var int */ private $timeStep = 30; /** * The Base32 encoder class * * @var Base32|null */ private $base32 = null; /** * Initialises an RFC6238-compatible TOTP generator. Please note that this * class does not implement the constraint in the last paragraph of §5.2 * of RFC6238. It's up to you to ensure that the same user/device does not * retry validation within the same Time Step. * * @param int $timeStep The Time Step (in seconds). Use 30 to be compatible with Google Authenticator. * @param int $passCodeLength The generated passcode length. Default: 6 digits. * @param int $secretLength The length of the secret key. Default: 10 bytes (80 bits). * @param Base32 $base32 The base32 en/decrypter */ public function __construct($timeStep = 30, $passCodeLength = 6, $secretLength = 10, Base32 $base32 = null) { $this->timeStep = $timeStep; $this->passCodeLength = $passCodeLength; $this->secretLength = $secretLength; $this->pinModulo = pow(10, $this->passCodeLength); if (is_null($base32)) { $this->base32 = new Base32(); } else { $this->base32 = $base32; } } /** * Get the time period based on the $time timestamp and the Time Step * defined. If $time is skipped or set to null the current timestamp will * be used. * * @param int|null $time Timestamp * * @return int The time period since the UNIX Epoch */ public function getPeriod($time = null) { if (is_null($time)) { $time = time(); } $period = floor($time / $this->timeStep); return $period; } /** * Check is the given passcode $code is a valid TOTP generated using secret * key $secret * * @param string $secret The Base32-encoded secret key * @param string $code The passcode to check * @param int $time The time to check it against. Leave null to check for the current server time. * * @return boolean True if the code is valid */ public function checkCode($secret, $code, $time = null) { $time = $this->getPeriod($time); for ($i = -1; $i <= 1; $i++) { if ($this->getCode($secret, ($time + $i) * $this->timeStep) == $code) { return true; } } return false; } /** * Gets the TOTP passcode for a given secret key $secret and a given UNIX * timestamp $time * * @param string $secret The Base32-encoded secret key * @param int $time UNIX timestamp * * @return string */ public function getCode($secret, $time = null) { $period = $this->getPeriod($time); $secret = $this->base32->decode($secret); $time = pack("N", $period); $time = str_pad($time, 8, chr(0), STR_PAD_LEFT); $hash = hash_hmac('sha1', $time, $secret, true); $offset = ord(substr($hash, -1)); $offset = $offset & 0xF; $truncatedHash = $this->hashToInt($hash, $offset) & 0x7FFFFFFF; $pinValue = str_pad($truncatedHash % $this->pinModulo, $this->passCodeLength, "0", STR_PAD_LEFT); return $pinValue; } /** * Extracts a part of a hash as an integer * * @param string $bytes The hash * @param string $start The char to start from (0 = first char) * * @return string */ protected function hashToInt($bytes, $start) { $input = substr($bytes, $start, strlen($bytes) - $start); $val2 = unpack("N", substr($input, 0, 4)); return $val2[1]; } /** * Returns a QR code URL for easy setup of TOTP apps like Google Authenticator * * @param string $user User * @param string $hostname Hostname * @param string $secret Secret string * * @return string */ public function getUrl($user, $hostname, $secret) { $url = sprintf("otpauth://totp/%s@%s?secret=%s", $user, $hostname, $secret); $encoder = "https://chart.googleapis.com/chart?chs=200x200&chld=Q|2&cht=qr&chl="; $encoderURL = $encoder . urlencode($url); return $encoderURL; } /** * Generates a (semi-)random Secret Key for TOTP generation * * @return string */ public function generateSecret() { $secret = ""; for ($i = 1; $i <= $this->secretLength; $i++) { $c = rand(0, 255); $secret .= pack("c", $c); } return $this->base32->encode($secret); } } Event/Dispatcher.php000064400000016075152325653710010446 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Event; use FOF30\Container\Container; defined('_JEXEC') or die; class Dispatcher implements Observable { /** @var Container The container this event dispatcher is attached to */ protected $container = null; /** @var array The observers attached to the dispatcher */ protected $observers = array(); /** @var array Maps events to observers */ protected $events = array(); /** * Public constructor * * @param Container $container The container this event dispatcher is attached to */ public function __construct(Container $container) { $this->container = $container; } /** * Returns the container this event dispatcher is attached to * * @return Container */ public function getContainer() { return $this->container; } /** * Attaches an observer to the object * * @param Observer $observer The observer to attach * * @return Dispatcher Ourselves, for chaining */ public function attach(Observer $observer) { $className = get_class($observer); // Make sure this observer is not already registered if (isset($this->observers[$className])) { return $this; } // Attach observer $this->observers[$className] = $observer; // Register the observable events $events = $observer->getObservableEvents(); foreach ($events as $event) { $event = strtolower($event); if (!isset($this->events[$event])) { $this->events[$event] = array($className); } else { $this->events[$event][] = $className; } } return $this; } /** * Detaches an observer from the object * * @param Observer $observer The observer to detach * * @return Dispatcher Ourselves, for chaining */ public function detach(Observer $observer) { $className = get_class($observer); // Make sure this observer is already registered if (!isset($this->observers[$className])) { return $this; } // Unregister the observable events $events = $observer->getObservableEvents(); foreach ($events as $event) { $event = strtolower($event); if (isset($this->events[$event])) { $key = array_search($className, $this->events[$event]); if ($key !== false) { unset($this->events[$event][$key]); if (empty($this->events[$event])) { unset ($this->events[$event]); } } } } // Detach observer unset($this->observers[$className]); return $this; } /** * Is an observer object already registered with this dispatcher? * * @param Observer $observer The observer to check if it's attached * * @return boolean */ public function hasObserver(Observer $observer) { $className = get_class($observer); return $this->hasObserverClass($className); } /** * Is there an observer of the specified class already registered with this dispatcher? * * @param string $className The observer class name to check if it's attached * * @return boolean */ public function hasObserverClass($className) { return isset($this->observers[$className]); } /** * Returns an observer attached to this behaviours dispatcher by its class name * * @param string $className The class name of the observer object to return * * @return null|Observer */ public function getObserverByClass($className) { if (!$this->hasObserverClass($className)) { return null; } return $this->observers[$className]; } /** * Triggers an event in the attached observers * * @param string $event The event to attach * @param array $args Arguments to the event handler * * @return array */ public function trigger($event, array $args = array()) { $event = strtolower($event); $result = array(); // Make sure the event is known to us, otherwise return an empty array if (!isset($this->events[$event]) || empty($this->events[$event])) { return $result; } foreach ($this->events[$event] as $className) { // Make sure the observer exists. if (!isset($this->observers[$className])) { continue; } // Get the observer $observer = $this->observers[$className]; // Make sure the method exists if (!method_exists($observer, $event)) { continue; } // Call the event handler and add its output to the return value. The switch allows for execution up to 2x // faster than using call_user_func_array switch (count($args)) { case 0: $result[] = $observer->{$event}(); break; case 1: $result[] = $observer->{$event}($args[0]); break; case 2: $result[] = $observer->{$event}($args[0], $args[1]); break; case 3: $result[] = $observer->{$event}($args[0], $args[1], $args[2]); break; case 4: $result[] = $observer->{$event}($args[0], $args[1], $args[2], $args[3]); break; case 5: $result[] = $observer->{$event}($args[0], $args[1], $args[2], $args[3], $args[4]); break; default: $result[] = call_user_func_array(array($observer, $event), $args); break; } } // Return the observers' result in an array return $result; } /** * Asks each observer to handle an event based on the provided arguments. The first observer to return a non-null * result wins. This is a *very* simplistic implementation of the Chain of Command pattern. * * @param string $event The event name to handle * @param array $args The arguments to the event * * @return mixed Null if the event can't be handled by any observer */ public function chainHandle($event, $args = array()) { $event = strtolower($event); $result = null; // Make sure the event is known to us, otherwise return an empty array if (!isset($this->events[$event]) || empty($this->events[$event])) { return $result; } foreach ($this->events[$event] as $className) { // Make sure the observer exists. if (!isset($this->observers[$className])) { continue; } // Get the observer $observer = $this->observers[$className]; // Make sure the method exists if (!method_exists($observer, $event)) { continue; } // Call the event handler and add its output to the return value. The switch allows for execution up to 2x // faster than using call_user_func_array switch (count($args)) { case 0: $result = $observer->{$event}(); break; case 1: $result = $observer->{$event}($args[0]); break; case 2: $result = $observer->{$event}($args[0], $args[1]); break; case 3: $result = $observer->{$event}($args[0], $args[1], $args[2]); break; case 4: $result = $observer->{$event}($args[0], $args[1], $args[2], $args[3]); break; case 5: $result = $observer->{$event}($args[0], $args[1], $args[2], $args[3], $args[4]); break; default: $result = call_user_func_array(array($observer, $event), $args); break; } if (!is_null($result)) { return $result; } } // Return the observers' result in an array return $result; } } Event/Observable.php000064400000001702152325653710010433 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Event; defined('_JEXEC') or die; /** * Interface Observable * * @codeCoverageIgnore */ interface Observable { /** * Attaches an observer to the object * * @param Observer $observer The observer to attach * * @return Observable Ourselves, for chaining */ public function attach(Observer $observer); /** * Detaches an observer from the object * * @param Observer $observer The observer to detach * * @return Observable Ourselves, for chaining */ public function detach(Observer $observer); /** * Triggers an event in the attached observers * * @param string $event The event to attach * @param array $args Arguments to the event handler * * @return array */ public function trigger($event, array $args = array()); } Event/Observer.php000064400000002715152325653710010143 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Event; defined('_JEXEC') or die; class Observer { /** @var Observable The object to observe */ protected $subject = null; protected $events = null; /** * Creates the observer and attaches it to the observable subject object * * @param Observable $subject The observable object to attach the observer to */ function __construct(Observable &$subject) { // Attach this observer to the subject $subject->attach($this); // Store a reference to the subject object $this->subject = $subject; } /** * Returns the list of events observable by this observer. Set the $this->events array manually for faster * processing, or let this method use reflection to return a list of all public methods. * * @return array */ public function getObservableEvents() { if (is_null($this->events)) { // Assign an empty array to protect us from behaviours without any valid method $this->events = array(); $reflection = new \ReflectionObject($this); $methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC); foreach ($methods as $m) { if ($m->name == 'getObservableEvents') { continue; } if ($m->name == '__construct') { continue; } $this->events[] = $m->name; } } return $this->events; } } Factory/Exception/ControllerNotFound.php000064400000001030152325653710014425 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Exception; use Exception; use RuntimeException; defined('_JEXEC') or die; class ControllerNotFound extends RuntimeException { public function __construct( $controller, $code = 500, Exception $previous = null ) { $message = \JText::sprintf('LIB_FOF_CONTROLLER_ERR_NOT_FOUND', $controller); parent::__construct( $message, $code, $previous ); } } Factory/Exception/DispatcherNotFound.php000064400000001042152325653710014373 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Exception; use Exception; use RuntimeException; defined('_JEXEC') or die; class DispatcherNotFound extends RuntimeException { public function __construct( $dispatcherClass, $code = 500, Exception $previous = null ) { $message = \JText::sprintf('LIB_FOF_DISPATCHER_ERR_NOT_FOUND', $dispatcherClass); parent::__construct( $message, $code, $previous ); } } Factory/Exception/FormLoadData.php000064400000001051152325653710013125 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Exception; use Exception; use RuntimeException; defined('_JEXEC') or die; class FormLoadData extends FormLoadGeneric { public function __construct( $message = "", $code = 500, Exception $previous = null ) { if (empty($message)) { $message = \JText::_('LIB_FOF_FORM_ERR_COULD_NOT_LOAD_FROM_DATA'); } parent::__construct( $message, $code, $previous ); } } Factory/Exception/FormLoadFile.php000064400000001023152325653710013132 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Exception; use Exception; use RuntimeException; defined('_JEXEC') or die; class FormLoadFile extends FormLoadGeneric { public function __construct( $file = "", $code = 500, Exception $previous = null ) { $message = \JText::sprintf('LIB_FOF_FORM_ERR_COULD_NOT_LOAD_FROM_FILE', $file); parent::__construct( $message, $code, $previous ); } } Factory/Exception/FormLoadGeneric.php000064400000000464152325653710013637 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Exception; use Exception; use RuntimeException; defined('_JEXEC') or die; class FormLoadGeneric extends RuntimeException { } Factory/Exception/FormNotFound.php000064400000001012152325653710013205 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Exception; use Exception; use RuntimeException; defined('_JEXEC') or die; class FormNotFound extends RuntimeException { public function __construct( $formClass, $code = 500, Exception $previous = null ) { $message = \JText::sprintf('LIB_FOF_FORM_ERR_NOT_FOUND', $formClass); parent::__construct( $message, $code, $previous ); } } Factory/Exception/ModelNotFound.php000064400000001016152325653710013346 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Exception; use Exception; use RuntimeException; defined('_JEXEC') or die; class ModelNotFound extends RuntimeException { public function __construct( $modelClass, $code = 500, Exception $previous = null ) { $message = \JText::sprintf('LIB_FOF_MODEL_ERR_NOT_FOUND', $modelClass); parent::__construct( $message, $code, $previous ); } } Factory/Exception/ToolbarNotFound.php000064400000001026152325653710013711 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Exception; use Exception; use RuntimeException; defined('_JEXEC') or die; class ToolbarNotFound extends RuntimeException { public function __construct( $toolbarClass, $code = 500, Exception $previous = null ) { $message = \JText::sprintf('LIB_FOF_TOOLBAR_ERR_NOT_FOUND', $toolbarClass); parent::__construct( $message, $code, $previous ); } } Factory/Exception/TransparentAuthenticationNotFound.php000064400000001046152325653710017512 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Exception; use Exception; use RuntimeException; defined('_JEXEC') or die; class TransparentAuthenticationNotFound extends RuntimeException { public function __construct( $taClass, $code = 500, Exception $previous = null ) { $message = \JText::sprintf('LIB_FOF_TRANSPARENTAUTH_ERR_NOT_FOUND', $taClass); parent::__construct( $message, $code, $previous ); } } Factory/Exception/ViewNotFound.php000064400000001012152325653710013214 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Exception; use Exception; use RuntimeException; defined('_JEXEC') or die; class ViewNotFound extends RuntimeException { public function __construct( $viewClass, $code = 500, Exception $previous = null ) { $message = \JText::sprintf('LIB_FOF_VIEW_ERR_NOT_FOUND', $viewClass); parent::__construct( $message, $code, $previous ); } } Factory/Magic/BaseFactory.php000064400000002166152325653710012124 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Magic; use FOF30\Container\Container; defined('_JEXEC') or die; abstract class BaseFactory { /** * @var Container|null The container where this factory belongs to */ protected $container = null; /** * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values * * @var string */ protected $section = 'auto'; /** * Public constructor * * @param Container $container The container we belong to */ public function __construct(Container $container) { $this->container = $container; } /** * @return string */ public function getSection() { return $this->section; } /** * @param string $section */ public function setSection($section) { $this->section = $section; } } Factory/Magic/ControllerFactory.php000064400000004207152325653710013373 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Magic; use FOF30\Controller\DataController; use FOF30\Factory\Exception\ControllerNotFound; defined('_JEXEC') or die; /** * Creates a DataControler object instance based on the information provided by the fof.xml configuration file */ class ControllerFactory extends BaseFactory { /** * Create a new object instance * * @param string $name The name of the class we're making * @param array $config The config parameters which override the fof.xml information * * @return DataController A new DataController object */ public function make($name = null, array $config = array()) { if (empty($name)) { throw new ControllerNotFound($name); } $appConfig = $this->container->appConfig; $name = ucfirst($name); $defaultConfig = array( 'name' => $name, 'default_task' => $appConfig->get("views.$name.config.default_task", 'main'), 'autoRouting' => $appConfig->get("views.$name.config.autoRouting", 1), 'csrfProtection' => $appConfig->get("views.$name.config.csrfProtection", 2), 'viewName' => $appConfig->get("views.$name.config.viewName", null), 'modelName' => $appConfig->get("views.$name.config.modelName", null), 'taskPrivileges' => $appConfig->get("views.$name.acl"), 'cacheableTasks' => $appConfig->get("views.$name.config.cacheableTasks", array( 'browse', 'read' )), 'taskMap' => $appConfig->get("views.$name.taskmap"), ); $config = array_merge($defaultConfig, $config); $className = $this->container->getNamespacePrefix($this->getSection()) . 'Controller\\DefaultDataController'; if (!class_exists($className, true)) { $className = 'FOF30\\Controller\\DataController'; } $controller = new $className($this->container, $config); $taskMap = $config['taskMap']; if (is_array($taskMap) && !empty($taskMap)) { foreach ($taskMap as $virtualTask => $method) { $controller->registerTask($virtualTask, $method); } } return $controller; } } Factory/Magic/DispatcherFactory.php000064400000002110152325653710013325 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Magic; use FOF30\Dispatcher\Dispatcher; defined('_JEXEC') or die; /** * Creates a Dispatcher object instance based on the information provided by the fof.xml configuration file */ class DispatcherFactory extends BaseFactory { /** * Create a new object instance * * @param array $config The config parameters which override the fof.xml information * * @return Dispatcher A new Dispatcher object */ public function make(array $config = array()) { $appConfig = $this->container->appConfig; $defaultConfig = $appConfig->get('dispatcher.*'); $config = array_merge($defaultConfig, $config); $className = $this->container->getNamespacePrefix($this->getSection()) . 'Dispatcher\\DefaultDispatcher'; if (!class_exists($className, true)) { $className = '\\FOF30\\Dispatcher\\Dispatcher'; } $dispatcher = new $className($this->container, $config); return $dispatcher; } } Factory/Magic/ModelFactory.php000064400000005541152325653710012312 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Magic; use FOF30\Model\DataModel; use FOF30\Factory\Exception\ModelNotFound; use FOF30\Model\TreeModel; defined('_JEXEC') or die; /** * Creates a DataModel/TreeModel object instance based on the information provided by the fof.xml configuration file */ class ModelFactory extends BaseFactory { /** * Create a new object instance * * @param string $name The name of the class we're making * @param array $config The config parameters which override the fof.xml information * * @return TreeModel|DataModel A new TreeModel or DataModel object */ public function make($name = null, array $config = array()) { if (empty($name)) { throw new ModelNotFound($name); } $appConfig = $this->container->appConfig; $name = ucfirst($name); $defaultConfig = array( 'name' => $name, 'use_populate' => $appConfig->get("models.$name.config.use_populate"), 'ignore_request' => $appConfig->get("models.$name.config.ignore_request"), 'tableName' => $appConfig->get("models.$name.config.tbl"), 'idFieldName' => $appConfig->get("models.$name.config.tbl_key"), 'knownFields' => $appConfig->get("models.$name.config.knownFields", null), 'autoChecks' => $appConfig->get("models.$name.config.autoChecks"), 'contentType' => $appConfig->get("models.$name.config.contentType"), 'fieldsSkipChecks' => $appConfig->get("models.$name.config.fieldsSkipChecks", array()), 'aliasFields' => $appConfig->get("models.$name.field", array()), 'behaviours' => $appConfig->get("models.$name.behaviors", array()), 'fillable_fields' => $appConfig->get("models.$name.config.fillable_fields", array()), 'guarded_fields' => $appConfig->get("models.$name.config.guarded_fields", array()), 'relations' => $appConfig->get("models.$name.relations", array()), ); $config = array_merge($defaultConfig, $config); // Get the default class names $dataModelClassName = $this->container->getNamespacePrefix($this->getSection()) . 'Model\\DefaultDataModel'; if (!class_exists($dataModelClassName, true)) { $dataModelClassName = '\\FOF30\\Model\\DataModel'; } $treeModelClassName = $this->container->getNamespacePrefix($this->getSection()) . 'Model\\DefaultTreeModel'; if (!class_exists($treeModelClassName, true)) { $treeModelClassName = '\\FOF30\\Model\\TreeModel'; } try { // First try creating a TreeModel $model = new $treeModelClassName($this->container, $config); } catch (DataModel\Exception\TreeIncompatibleTable $e) { // If the table isn't a nested set, create a regular DataModel $model = new $dataModelClassName($this->container, $config); } return $model; } } Factory/Magic/TransparentAuthenticationFactory.php000064400000002246152325653710016452 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Magic; use FOF30\Dispatcher\Dispatcher; defined('_JEXEC') or die; /** * Creates a TransparentAuthentication object instance based on the information provided by the fof.xml configuration file */ class TransparentAuthenticationFactory extends BaseFactory { /** * Create a new object instance * * @param array $config The config parameters which override the fof.xml information * * @return Dispatcher A new Dispatcher object */ public function make(array $config = array()) { $appConfig = $this->container->appConfig; $defaultConfig = $appConfig->get('authentication.*'); $config = array_merge($defaultConfig, $config); $className = $this->container->getNamespacePrefix($this->getSection()) . 'TransparentAuthentication\\DefaultTransparentAuthentication'; if (!class_exists($className, true)) { $className = '\\FOF30\\TransparentAuthentication\\TransparentAuthentication'; } $dispatcher = new $className($this->container, $config); return $dispatcher; } } Factory/Magic/ViewFactory.php000064400000004012152325653710012154 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Magic; use FOF30\Factory\Exception\ViewNotFound; use FOF30\View\DataView\DataViewInterface; defined('_JEXEC') or die; /** * Creates a DataModel/TreeModel object instance based on the information provided by the fof.xml configuration file */ class ViewFactory extends BaseFactory { /** * Create a new object instance * * @param string $name The name of the class we're making * @param string $viewType The view type, default html, possible values html, form, raw, json, csv * @param array $config The config parameters which override the fof.xml information * * @return DataViewInterface A new TreeModel or DataModel object */ public function make($name = null, $viewType = 'html', array $config = array()) { if (empty($name)) { throw new ViewNotFound("[name : type] = [$name : $viewType]"); } $appConfig = $this->container->appConfig; $name = ucfirst($name); $defaultConfig = array( 'name' => $name, 'template_path' => $appConfig->get("views.$name.config.template_path"), 'layout' => $appConfig->get("views.$name.config.layout"), // You can pass something like .php => Class1, .foo.bar => Class 2 'viewEngineMap' => $appConfig->get("views.$name.config.viewEngineMap"), ); $config = array_merge($defaultConfig, $config); $className = $this->container->getNamespacePrefix($this->getSection()) . 'View\\DataView\\Default' . ucfirst($viewType); if (!class_exists($className, true)) { $className = '\\FOF30\\View\\DataView\\' . ucfirst($viewType); } if (!class_exists($className, true)) { $className = $this->container->getNamespacePrefix($this->getSection()) . 'View\\DataView\\DefaultHtml'; } if (!class_exists($className)) { $className = '\\FOF30\\View\\DataView\\Html'; } $view = new $className($this->container, $config); return $view; } } Factory/Scaffolding/Controller/Builder.php000064400000004645152325653710014636 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Controller; use FOF30\Container\Container; use FOF30\Factory\Magic\ControllerFactory; defined('_JEXEC') or die; /** * Scaffolding Builder * * @package FOF30\Factory\Scaffolding * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Builder { /** @var \FOF30\Container\Container The container we belong to */ protected $container = null; /** * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values * * @var string */ protected $section = 'auto'; /** * Create the scaffolding builder instance * * @param \FOF30\Container\Container $c */ public function __construct(Container $c) { $this->container = $c; } /** * Make a new scaffolding document * * @param string $requestedClass The requested class, with full qualifier ie Myapp\Site\Controller\Foobar * @param string $viewName The name of the view linked to this controller * * @return bool True on success, false otherwise */ public function make($requestedClass, $viewName) { // Class already exists? Stop here if (class_exists($requestedClass)) { return true; } // I have to magically create the controller class $magic = new ControllerFactory($this->container); $magic->setSection($this->getSection()); $fofController = $magic->make($viewName); /** @var ErectorInterface $erector */ $erector = new ControllerErector($this, $fofController, $viewName); $erector->setSection($this->getSection()); $erector->build(); if(!class_exists($requestedClass)) { return false; } return true; } /** * Gets the container this builder belongs to * * @return Container */ public function getContainer() { return $this->container; } /** * @return string */ public function getSection() { return $this->section; } /** * @param string $section */ public function setSection($section) { $this->section = $section; } } Factory/Scaffolding/Controller/ControllerErector.php000064400000005627152325653710016720 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Controller; use FOF30\Controller\DataController; defined('_JEXEC') or die; /** * @package FOF30\Factory\Scaffolding * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class ControllerErector implements ErectorInterface { /** * The Builder which called us * * @var \FOF30\Factory\Scaffolding\Controller\Builder */ protected $builder = null; /** * The Controller attached to the view we're building * * @var \FOF30\Controller\DataController */ protected $controller = null; /** * The name of our view * * @var string */ protected $viewName = null; /** * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values * * @var string */ protected $section = 'auto'; public function __construct(Builder $parent, DataController $controller, $viewName) { $this->builder = $parent; $this->controller = $controller; $this->viewName = $viewName; } public function build() { $container = $this->builder->getContainer(); $fullPath = $container->getNamespacePrefix($this->getSection()) . 'Controller\\' . ucfirst($container->inflector->singularize($this->viewName)); // Let's remove the last part and use it to create the class name $parts = explode('\\', trim($fullPath, '\\')); $className = array_pop($parts); // Now glue everything together $namespace = implode('\\', $parts); // Let's be sure that the parent class extends with a backslash $baseClass = '\\'.trim(get_class($this->controller), '\\'); $code = '<?php'.PHP_EOL; $code .= PHP_EOL; $code .= 'namespace '.$namespace.';'.PHP_EOL; $code .= PHP_EOL; $code .= "defined('_JEXEC') or die;".PHP_EOL; $code .= PHP_EOL; $code .= 'class '.$className.' extends '.$baseClass.PHP_EOL; $code .= '{'.PHP_EOL; $code .= PHP_EOL; $code .= '}'.PHP_EOL; $path = $container->backEndPath; if(in_array('Site', $parts)) { $path = $container->frontEndPath; } $path .= '/Controller/'.$className.'.php'; $filesystem = $container->filesystem; $filesystem->fileWrite($path, $code); return $path; } /** * @return string */ public function getSection() { return $this->section; } /** * @param string $section */ public function setSection($section) { $this->section = $section; } } Factory/Scaffolding/Controller/ErectorInterface.php000064400000002227152325653710016466 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Controller; use FOF30\Controller\DataController; defined('_JEXEC') or die; /** * Interface ErectorInterface * @package FOF30\Factory\Scaffolding\Controller * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ interface ErectorInterface { /** * Construct the erector object * * @param Builder $parent The parent builder * @param \FOF30\Controller\DataController $controller The controller we're erecting a scaffold against * @param string $viewName The view name for this controller */ public function __construct(Builder $parent, DataController $controller, $viewName); /** * Erects a scaffold. It then uses the parent's methods to assign the erected scaffold. * * @return void */ public function build(); /** * @return string */ public function getSection(); /** * @param string $section */ public function setSection($section); } Factory/Scaffolding/Layout/BaseErector.php000064400000014671152325653710014600 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Layout; use FOF30\Model\DataModel; defined('_JEXEC') or die; /** * Class BaseErector * @package FOF30\Factory\Scaffolding\Layout * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class BaseErector implements ErectorInterface { /** * The Builder which called us * * @var \FOF30\Factory\Scaffolding\Layout\Builder */ protected $builder = null; /** * The Model attached to the view we're building * * @var \FOF30\Model\DataModel */ protected $model = null; /** * The name of our view * * @var string */ protected $viewName = null; /** * The XML document we're constructing * * @var \SimpleXMLElement */ protected $xml; /** * The common language key prefix, e.g. COM_EXAMPLE_MYVIEW_ * * @var null */ private $langKeyPrefix = null; /** * Strings to add to the language definition * * @var array */ private $strings = array(); /** * Construct the erector object * * @param \FOF30\Factory\Scaffolding\Layout\Builder $parent The parent builder * @param \FOF30\Model\DataModel $model The model we're erecting a scaffold against * @param string $viewName The view name for this model */ public function __construct(Builder $parent, DataModel $model, $viewName) { $this->builder = $parent; $this->model = $model; $this->viewName = $viewName; $this->xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><form></form>'); } /** * Erects a scaffold. It then uses the parent's setXml and setStrings to assign the erected scaffold and the * additional language strings to the parent which will decide what to do with that. * * @return void * * @throws \LogicException Because it's not implemented */ public function build() { throw new \LogicException('You need to implement build() in your Erector class'); } /** * Returns the common language key prefix, something like "COM_EXAMPLE_MYVIEW_" * * @return string */ protected function getLangKeyPrefix() { if (empty($this->langKeyPrefix)) { $prefix = $key = $this->builder->getContainer()->componentName . '_' . $this->viewName . '_'; $this->langKeyPrefix = strtoupper($prefix); } return $this->langKeyPrefix; } /** * Returns the language definition for a field. The hashed array has two keys, label and desc, each one containing * the language definition for the label and description of the field. Each definition has the keys key and value * with the language key and actual language string. * * @param string $fieldName * * @return array */ protected function getFieldLabel($fieldName) { $fieldNameForKey = strtoupper($fieldName); $definition = array( 'label' => array( 'key' => $this->getLangKeyPrefix() . $fieldNameForKey . '_LABEL', 'value' => ucfirst($fieldName), ), 'desc' => array( 'key' => $this->getLangKeyPrefix() . $fieldNameForKey . '_DESC', 'value' => 'Description for ' . ucfirst($fieldName), ) ); return $definition; } /** * Convert the database type into something we can use * * @param string $type The type of the database field * * @return array */ public static function getFieldType($type) { if (empty($type)) { return null; } // Remove parentheses, indicating field options / size (they don't matter in type detection) if (strpos($type, '(') === false) { $type .= '()'; } list($type, $parameters) = explode('(', $type); $detectedType = null; $detectedParameters = null; $type = strtolower($type); switch (trim($type)) { case 'varchar': case 'text': case 'char': case 'character varying': case 'nvarchar': case 'nchar': $detectedType = 'Text'; break; case 'smalltext': case 'longtext': case 'mediumtext': $detectedType = 'Text'; break; case 'date': case 'datetime': case 'time': case 'year': case 'timestamp': case 'timestamp without time zone': case 'timestamp with time zone': $detectedType = 'Calendar'; break; case 'tinyint': case 'smallint': $detectedType = 'Checkbox'; break; case 'int': case 'integer': case 'bigint': // Because the Integer field is rendered in Joomla! as a drop-down list. Ugh!!! $detectedType = 'Number'; break; case 'float': case 'double': case 'currency': $detectedType = 'Number'; break; case 'enum': $detectedType = 'GenericList'; $parameters = trim($parameters, "\t\n\r\0\x0B )"); $detectedParameters = explode(',', $parameters); $detectedParameters = array_map(function ($x) { return trim($x, "'\n\r\t\0\x0B"); }, $detectedParameters); $temp = array(); foreach ($detectedParameters as $v) { $temp[$v] = $v; } $detectedParameters = $temp; break; } // Sometimes we have character types followed by a space and some cruft. Let's handle them. if (is_null($detectedType) && !empty($type)) { list ($type, ) = explode(' ', $type); switch (trim($type)) { case 'varchar': case 'text': case 'char': case 'character varying': case 'nvarchar': case 'nchar': $detectedType = 'Text'; break; case 'smalltext': case 'longtext': case 'mediumtext': $detectedType = 'Text'; break; case 'date': case 'datetime': case 'time': case 'year': case 'timestamp': $detectedType = 'Calendar'; break; case 'tinyint': case 'smallint': $detectedType = 'Checkbox'; break; default: $detectedType = 'Integer'; break; } } // If all else fails assume it's a Text and hope for the best if (empty($detectedType)) { $detectedType = 'Text'; } return array('type' => $detectedType, 'params' => $detectedParameters); } /** * Adds a language string definition as long as it doesn't exist in the existing language file. * * @param string $key The language string key * @param string $value The language string */ protected function addString($key, $value) { if (\JText::_($key) != $key) { return; } $this->strings[$key] = $value; } /** * Push the form and strings to the builder */ protected function pushResults() { $this->builder->setStrings($this->strings); $this->builder->setXml($this->xml); } } Factory/Scaffolding/Layout/BrowseErector.php000064400000052571152325653710015170 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Layout; use FOF30\Model\DataModel; defined('_JEXEC') or die; /** * Erects a scaffolding XML for browse views * * @package FOF30\Factory\Scaffolding * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class BrowseErector extends BaseErector implements ErectorInterface { public function build() { // Get a reference to the model $model = $this->model; // Create the "no records" language string $noRowsKey = strtoupper($this->builder->getContainer()->componentName) . '_COMMON_NORECORDS'; $this->addString($noRowsKey, 'There are no records to display'); // Create the attributes of the form's base element $this->xml->addAttribute('type', 'browse'); $this->xml->addAttribute('show_header', "1"); $this->xml->addAttribute('show_filters', "1"); $this->xml->addAttribute('show_pagination', "1"); $this->xml->addAttribute('norows_placeholder', $noRowsKey); // Create the headerset and fieldset sections of the form file $headerSet = $this->xml->addChild('headerset'); $fieldSet = $this->xml->addChild('fieldset'); $fieldSet->addAttribute('name', 'items'); // Get the database fields $allFields = $model->getTableFields(); // Ordering must go first if ($model->hasField('ordering')) { $this->applyOrderingField($model, $headerSet, $fieldSet, $allFields); } // Primary key field goes next $this->applyPrimaryKeyField($model, $headerSet, $fieldSet, $allFields); // Get a list of "do not display" fields $doNotShow = $this->getDoNotShow(); foreach ($allFields as $fieldName => $fieldDefinition) { // Skip the fields which shouldn't be displayed if (in_array($fieldName, $doNotShow)) { continue; } // Get the lowercase field name and prepare to handle specially named fields $lowercaseFieldName = strtolower($fieldName); // access => AccessLevel if ($model->getFieldAlias('access') == $fieldName) { $this->applyAccessLevelField($model, $headerSet, $fieldSet, $fieldName); continue; } // title => Title if ($model->getFieldAlias('title') == $fieldName) { $this->applyTitleField($model, $headerSet, $fieldSet, $fieldName); continue; } // slug => Hide if there is a title field as well if ($model->getFieldAlias('slug') == $fieldName) { $titleField = $model->getFieldAlias('title'); if (array_key_exists($titleField, $allFields)) { continue; } } // tag => Tag if ($model->getFieldAlias('tag') == $fieldName) { $this->applyTagField($model, $headerSet, $fieldSet, $fieldName); continue; } // enabled => Actions if ($model->getFieldAlias('enabled') == $fieldName) { $this->applyActionsField($model, $headerSet, $fieldSet, $fieldName); continue; } // cache_handler => CacheHandler if ($lowercaseFieldName == 'cache_handler') { $this->applyCacheHandlerField($model, $headerSet, $fieldSet, $fieldName); continue; } // component_id => Components if ($lowercaseFieldName == 'component_id') { $this->applyComponentsField($model, $headerSet, $fieldSet, $fieldName); continue; } // body, introtext, fulltext => Editor if (in_array($lowercaseFieldName, array('body', 'introtext', 'fulltext', 'description'))) { $this->applyEditorField($model, $headerSet, $fieldSet, $fieldName); continue; } // email, *_email => Email if (($lowercaseFieldName == 'email') || (substr($lowercaseFieldName, -6) == 'email')) { $this->applyEmailField($model, $headerSet, $fieldSet, $fieldName); continue; } // image, media, *_image => Media if ( in_array($lowercaseFieldName, array('image', 'media')) || (substr($lowercaseFieldName, -6) == '_image') ) { $this->applyMediaField($model, $headerSet, $fieldSet, $fieldName); continue; } // language, lang, lang_id => Language if (in_array($lowercaseFieldName, array('language', 'lang', 'lang_id'))) { $this->applyLanguageField($model, $headerSet, $fieldSet, $fieldName); continue; } // password, passwd, pass => Password if (in_array($lowercaseFieldName, array('password', 'passwd', 'pass'))) { $this->applyPasswordField($model, $headerSet, $fieldSet, $fieldName); continue; } // plugin_id => Plugins if ($lowercaseFieldName == 'plugin_id') { $this->applyPluginsField($model, $headerSet, $fieldSet, $fieldName); continue; } // asset_id => Rules (not applicable here) if ($lowercaseFieldName == 'asset_id') { continue; } // session_handler => SessionHandler if ($lowercaseFieldName == 'session_handler') { $this->applySessionHandlerField($model, $headerSet, $fieldSet, $fieldName); continue; } // tel, telephone, phone => Tel if (in_array($lowercaseFieldName, array('tel', 'telephone', 'phone'))) { $this->applyTelField($model, $headerSet, $fieldSet, $fieldName); continue; } // timezone, tz, time_zone => Timezone if (in_array($lowercaseFieldName, array('timezone', 'tz', 'time_zone'))) { $this->applyTimezoneField($model, $headerSet, $fieldSet, $fieldName); continue; } // url, link, href => Url if (in_array($lowercaseFieldName, array('url', 'link', 'href'))) { $this->applyUrlField($model, $headerSet, $fieldSet, $fieldName); continue; } // user, user_id, userid, uid => User if (in_array($lowercaseFieldName, array('user', 'user_id', 'userid', 'uid'))) { $this->applyUserField($model, $headerSet, $fieldSet, $fieldName); continue; } // group, group_id, groupid, gid => UserGroup if (in_array($lowercaseFieldName, array('group', 'group_id', 'groupid', 'gid'))) { $this->applyUserGroupField($model, $headerSet, $fieldSet, $fieldName); continue; } // Special handling for myComponent_whatever_id fields $myComponentPrefix = $this->builder->getContainer()->bareComponentName . '_'; if ((strpos($fieldName, $myComponentPrefix) === 0) && (substr($fieldName, -3) == '_id')) { $parts = explode('_', $fieldName); array_pop($parts); array_shift($parts); // myComponent_something_id => Relation or Model if (count($parts) == 1) { $foreignName = array_shift($parts); } // myComponent_something_another_id => Relation else { $foreignName1 = array_shift($parts); $foreignName1 = $this->model->getContainer()->inflector->pluralize($foreignName1); $foreignName2 = array_shift($parts); $foreignName2 = $this->model->getContainer()->inflector->pluralize($foreignName2); $modelName = $model->getName(); $modelName = $this->model->getContainer()->inflector->pluralize($modelName); $foreignName = ($foreignName1 == $modelName) ? $foreignName2 : $foreignName1; } try { $model->getRelations()->getRelation($foreignName); $this->applyRelationField($model, $headerSet, $fieldSet, $fieldName); continue; } catch (DataModel\Relation\Exception\RelationNotFound $e) { $foreignName = $this->model->getContainer()->inflector->pluralize($foreignName); try { $this->applyModelField($model, $headerSet, $fieldSet, $fieldName, $foreignName); continue; } catch (\Exception $e) { } } } // Other fields, use getFieldType $typeDef = $this->getFieldType($fieldDefinition->Type); switch ($typeDef['type']) { case 'Text': $this->applyTextField($model, $headerSet, $fieldSet, $fieldName); break; case 'Editor': $this->applyEditorField($model, $headerSet, $fieldSet, $fieldName); break; case 'Calendar': $this->applyCalendarField($model, $headerSet, $fieldSet, $fieldName); break; case 'Checkbox': $this->applyCheckboxField($model, $headerSet, $fieldSet, $fieldName); break; case 'Integer': $this->applyIntegerField($model, $headerSet, $fieldSet, $fieldName); break; case 'Number': $this->applyNumberField($model, $headerSet, $fieldSet, $fieldName); break; case 'GenericList': $this->applyGenericListField($model, $headerSet, $fieldSet, $fieldName, $typeDef['params']); break; } } $this->pushResults(); } /** * Apply the ordering field * * @param \FOF30\Model\DataModel $model * @param \SimpleXMLElement $headerSet * @param \SimpleXMLElement $fieldSet * @param array $allFields */ private function applyOrderingField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, array &$allFields) { $langDefs = $this->getFieldLabel('ordering'); $this->addString($langDefs['label']['key'], $langDefs['label']['value']); $this->addString($langDefs['desc']['key'], $langDefs['desc']['value']); $fieldName = $model->getFieldAlias('ordering'); $header = $headerSet->addChild('header'); $header->addAttribute('name', $fieldName); $header->addAttribute('type', 'Ordering'); $header->addAttribute('label', $langDefs['label']['key']); $header->addAttribute('sortable', 'true'); $header->addAttribute('tdwidth', '1%'); $field = $fieldSet->addChild('field'); $field->addAttribute('name', $fieldName); $field->addAttribute('type', 'Ordering'); $field->addAttribute('class', 'input-mini input-sm'); unset($allFields[$fieldName]); } /** * Apply the ordering field * * @param \FOF30\Model\DataModel $model * @param \SimpleXMLElement $headerSet * @param \SimpleXMLElement $fieldSet * @param array $allFields */ private function applyPrimaryKeyField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, array &$allFields) { $keyField = $model->getKeyName(); $langDefs = $this->getFieldLabel($keyField); $this->addString($langDefs['label']['key'], $langDefs['label']['value']); $this->addString($langDefs['desc']['key'], $langDefs['desc']['value']); $header = $headerSet->addChild('header'); $header->addAttribute('name', $keyField); $header->addAttribute('type', 'RowSelect'); $header->addAttribute('label', $langDefs['label']['key']); $header->addAttribute('sortable', 'true'); $header->addAttribute('tdwidth', '20'); $field = $fieldSet->addChild('field'); $field->addAttribute('name', $keyField); $field->addAttribute('type', 'SelectRow'); unset($allFields[$keyField]); } private function applyFieldOfType(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName, $fieldTypeHeader, $fieldTypeField, array $headerAttributes = array()) { $langDefs = $this->getFieldLabel($fieldName); $this->addString($langDefs['label']['key'], $langDefs['label']['value']); $this->addString($langDefs['desc']['key'], $langDefs['desc']['value']); $header = $headerSet->addChild('header'); $header->addAttribute('name', $fieldName); $header->addAttribute('type', $fieldTypeHeader); $header->addAttribute('label', $langDefs['label']['key']); if (!empty($headerAttributes)) { foreach ($headerAttributes as $k => $v) { $header->addAttribute($k, $v); } } $field = $fieldSet->addChild('field'); $field->addAttribute('name', $fieldName); $field->addAttribute('type', $fieldTypeField); } /** * Apply an access level field * * @param \FOF30\Model\DataModel $model * @param \SimpleXMLElement $headerSet * @param \SimpleXMLElement $fieldSet * @param string $fieldName */ private function applyAccessLevelField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'AccessLevel', 'AccessLevel', array( 'sortable' => 'true' )); } private function applyActionsField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Published', 'Actions', array( 'sortable' => 'true' )); } private function applyCacheHandlerField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'CacheHandler', array( 'sortable' => 'true' )); } private function applyCalendarField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Date', 'Calendar', array( 'sortable' => 'true' )); } private function applyCheckboxField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Checkbox', array( 'sortable' => 'true' )); } private function applyComponentsField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Components', array( 'sortable' => 'true' )); } private function applyEditorField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Editor', array( 'sortable' => 'true' )); } private function applyEmailField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Email', array( 'sortable' => 'true' )); } private function applyIntegerField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Integer', array( 'sortable' => 'true' )); } private function applyNumberField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Number', array( 'sortable' => 'true' )); } private function applyMediaField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Media'); } private function applyLanguageField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Language', 'Language', array( 'sortable' => 'true' )); } private function applyPasswordField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Password', array( 'sortable' => 'true' )); } private function applyPluginsField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Plugins', array( 'sortable' => 'true' )); } private function applySessionHandlerField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'SessionHandler', array( 'sortable' => 'true' )); } private function applyTelField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Tel', array( 'sortable' => 'true' )); } private function applyTextField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Text', array( 'sortable' => 'true' )); } private function applyTimezoneField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Timezone', array( 'sortable' => 'true' )); } private function applyUrlField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'Url', array( 'sortable' => 'true' )); } private function applyUserField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'User', array( 'sortable' => 'true' )); } private function applyUserGroupField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Searchable', 'UserGroup', array( 'sortable' => 'true' )); } private function applyRelationField($model, $headerSet, $fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Relation', array( 'sortable' => 'true' )); } private function applyTagField($model, $headerSet, $fieldSet, $fieldName) { $this->applyFieldOfType($model, $headerSet, $fieldSet, $fieldName, 'Field', 'Tag', array( 'sortable' => 'true' )); } private function applyTitleField($model, \SimpleXMLElement $headerSet, \SimpleXMLElement $fieldSet, $fieldName) { $langDefs = $this->getFieldLabel($fieldName); $this->addString($langDefs['label']['key'], $langDefs['label']['value']); $this->addString($langDefs['desc']['key'], $langDefs['desc']['value']); $header = $headerSet->addChild('header'); $header->addAttribute('name', $fieldName); $header->addAttribute('type', 'Searchable'); $header->addAttribute('label', $langDefs['label']['key']); if (!empty($headerAttributes)) { foreach ($headerAttributes as $k => $v) { $header->addAttribute($k, $v); } } $field = $fieldSet->addChild('field'); $field->addAttribute('name', $fieldName); $field->addAttribute('type', 'Sortable'); $field->addAttribute('url', 'index.php?option=' . $this->builder->getContainer()->componentName . '&view=' . $this->model->getContainer()->inflector->singularize($this->viewName) . '&id=[ITEM:ID]&[TOKEN]=1' ); } private function applyModelField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName, $modelName) { // This will fail if the model is invalid, e.g. we have example_foobar_id but no #__example_foobars table. The // error will balloon up the stack and the field will be rendered as simple number field instead of a Model // field. /** @var DataModel $foreignModel */ $foreignModel = $model->getContainer()->factory->model($modelName); $value_field = $foreignModel->getKeyName(); if ($foreignModel->hasField('title')) { $value_field = $foreignModel->getFieldAlias('title'); } $langDefs = $this->getFieldLabel($fieldName); $this->addString($langDefs['label']['key'], $langDefs['label']['value']); $this->addString($langDefs['desc']['key'], $langDefs['desc']['value']); $header = $headerSet->addChild('header'); $header->addAttribute('name', $fieldName); $header->addAttribute('type', 'Model'); $header->addAttribute('model', $modelName); $header->addAttribute('key_field', $foreignModel->getKeyName()); $header->addAttribute('value_field', $value_field); $header->addAttribute('label', $langDefs['label']['key']); $header->addAttribute('sortable', 'true'); $field = $fieldSet->addChild('field'); $field->addAttribute('name', $fieldName); $field->addAttribute('type', 'Model'); $field->addAttribute('model', $modelName); $field->addAttribute('key_field', $foreignModel->getKeyName()); $field->addAttribute('value_field', $value_field); } private function applyGenericListField(DataModel $model, \SimpleXMLElement &$headerSet, \SimpleXMLElement &$fieldSet, $fieldName, $options) { $displayOptions = array(); foreach ($options as $k => $v) { $langKey = $this->builder->getContainer()->componentName . '_' . $this->viewName . '_' . $fieldName . '_OPT_' . $k; $this->addString($langKey, $v); $displayOptions[$k] = $langKey; } $langDefs = $this->getFieldLabel($fieldName); $this->addString($langDefs['label']['key'], $langDefs['label']['value']); $this->addString($langDefs['desc']['key'], $langDefs['desc']['value']); $header = $headerSet->addChild('header'); $header->addAttribute('name', $fieldName); $header->addAttribute('type', 'Selectable'); $header->addAttribute('label', $langDefs['label']['key']); $header->addAttribute('sortable', 'true'); foreach ($displayOptions as $k => $v) { $header->addChild('option', $v)->addAttribute('value', $k); } $field = $fieldSet->addChild('field'); $field->addAttribute('name', $fieldName); $field->addAttribute('type', 'GenericList'); foreach ($displayOptions as $k => $v) { $field->addChild('option', $v)->addAttribute('value', $k); } } /** * Create a list of fields which should not be shown in the form. These are fields like created/modified/locked * user and time and other internal fields which should not be part of the form output. * * @return array */ private function getDoNotShow() { $return = array(); $checkFields = array('created_by', 'created_on', 'modified_by', 'modified_on', 'locked_by', 'locked_on'); foreach ($checkFields as $checkField) { $return[] = $this->model->getFieldAlias($checkField); } return $return; } } Factory/Scaffolding/Layout/Builder.php000064400000015517152325653710013770 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Layout; use FOF30\Container\Container; use SimpleXMLElement; defined('_JEXEC') or die; /** * Scaffolding Builder * * Creates an automatic XML form definition to render a view based on the database fields you've got in the model. This * is not designed for production; it's designed to give you a way to quickly add some test data to your component * and get started really fast with FOF development. * * @package FOF30\Factory\Scaffolding * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Builder { /** @var \FOF30\Container\Container The container we belong to */ protected $container = null; /** @var bool Should I save the scaffolding results? */ protected $saveScaffolding = false; /** @var SimpleXMLElement The form we will be returning to the caller */ protected $xml; /** @var array Language string definitions we need to add to the component's language file */ protected $strings = array(); /** * Create the scaffolding builder instance * * @param \FOF30\Container\Container $c */ public function __construct(Container $c) { $this->container = $c; $this->saveScaffolding = $this->container->factory->isSaveScaffolding(); } /** * Make a new scaffolding document * * @param string $requestedFilename The requested filename, e.g. form.default.xml * @param string $viewName The name of the view this form will be used to render * * @return string|null The XML source or null if we can't make a scaffolding XML */ public function make($requestedFilename, $viewName) { // Initialise $this->xml = null; $this->strings = array(); // The requested filename should be in the format "form.SOMETHING.xml" if (substr($requestedFilename, 0, 5) !== 'form.') { return null; } // Get the requested form type $formType = substr($requestedFilename, 5); // Make sure the requested form type is supported by this builder if (!in_array($formType, array('default', 'form', 'item'))) { return null; } switch ($formType) { default: case 'default': $builderType = 'Browse'; break; case 'form': $builderType = 'Form'; break; case 'item': $builderType = 'Item'; break; } // Get the model $model = $this->container->factory->model($viewName); // Create the scaffolding object and build the XML file $className = 'FOF30\\Factory\\Scaffolding\\Layout\\' . $builderType . 'Erector'; /** @var ErectorInterface $erector */ $erector = new $className($this, $model, $viewName); $erector->build(); if ($this->saveScaffolding) { $this->saveXml($requestedFilename, $viewName); $this->saveStrings(); } $this->applyStrings(); return $this->xml->asXML(); } /** * Set the XML form document * * @param SimpleXMLElement $xml The XML document to set */ public function setXml(SimpleXMLElement $xml) { $this->xml = $xml; } /** * Set the additional strings array * * @param array $strings The strings array to set */ public function setStrings(array $strings) { $this->strings = $strings; } /** * Load the strings array in Joomla!'s JLanguage object */ protected function applyStrings() { // If we don't have language strings there's no point continuing if (empty($this->strings)) { return; } // Get a temporary filename $baseDirs = $this->container->platform->getPlatformBaseDirs(); $tempDir = $baseDirs['tmp']; $filename = tempnam($tempDir, 'fof'); if ($filename === false) { return; } // Save the strings to a temporary file $this->saveStrings($filename); // Load the temporary file $lang = $this->container->platform->getLanguage(); $langReflection = new \ReflectionObject($lang); $loadLangReflection = $langReflection->getMethod('loadLanguage'); $loadLangReflection->setAccessible(true); $loadLangReflection->invoke($lang, $filename, $this->container->componentName); // Delete temporary filename @unlink($filename); } /** * Gets the container this builder belongs to * * @return Container */ public function getContainer() { return $this->container; } /** * Save the XML form as a file * * @param string $requestedFilename The requested filename, e.g. form.default.xml * @param string $viewName The name of the view this form will be used to render */ protected function saveXml($requestedFilename, $viewName) { $path = $this->container->frontEndPath; if ($this->container->platform->isBackend()) { $path = $this->container->backEndPath; } $targetFilename = $path . '/View/' . $viewName . '/tmpl/' . $requestedFilename; $directory = dirname($targetFilename); if (!is_dir($directory)) { $createdDirectory = @mkdir($directory, 0755, true); if (!@$createdDirectory) { \JLoader::import('joomla.filesystem.folder'); \JFolder::create($directory, 0755); } } $xml = $this->xml->asXML(); $domDocument = new \DOMDocument('1.0'); $domDocument->loadXML($xml); $domDocument->preserveWhiteSpace = false; $domDocument->formatOutput = true; $xml = $domDocument->saveXML(); $saveResult = @file_put_contents($targetFilename . '.xml', $xml); if ($saveResult === false) { \JLoader::import('joomla.filesystem.file'); \JFile::write($targetFilename, $xml); } } /** * Saves the language strings, merged with any old ones, to a Joomla! INI language file * * @param string $targetFilename The full path to the INI file, leave blank for auto-detection */ protected function saveStrings($targetFilename = null) { // If no filename is defined, get the component's language definition filename if (empty($targetFilename)) { $jLang = $this->container->platform->getLanguage(); $basePath = $this->container->platform->isBackend() ? JPATH_ADMINISTRATOR : JPATH_SITE; $lang = $jLang->setLanguage('en-GB'); $jLang->setLanguage($lang); $path = $jLang->getLanguagePath($basePath, $lang); $targetFilename = $path . '/' . $lang . '.' . $this->container->componentName . '.ini'; } // Try to load the existing language file $strings = array(); if (@file_exists($targetFilename)) { $contents = file_get_contents($targetFilename); $contents = str_replace('_QQ_', '"\""', $contents); $strings = @parse_ini_string($contents); } $strings = array_merge($strings, $this->strings); // Create the INI file $iniFile = ''; foreach ($strings as $k => $v) { $iniFile .= strtoupper($k) . '="' . str_replace('"', '"_QQ_"', $v) . "\"\n"; } // Save it $saveResult = @file_put_contents($targetFilename, $iniFile); if ($saveResult === false) { \JLoader::import('joomla.filesystem.file'); \JFile::write($targetFilename, $iniFile); } } } Factory/Scaffolding/Layout/ErectorInterface.php000064400000002106152325653710015614 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Layout; use FOF30\Model\DataModel; defined('_JEXEC') or die; /** * Interface ErectorInterface * @package FOF30\Factory\Scaffolding\Layout * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ interface ErectorInterface { /** * Construct the erector object * * @param \FOF30\Factory\Scaffolding\Layout\Builder $parent The parent builder * @param \FOF30\Model\DataModel $model The model we're erecting a scaffold against * @param string $viewName The view name for this model */ public function __construct(Builder $parent, DataModel $model, $viewName); /** * Erects a scaffold. It then uses the parent's setXml and setStrings to assign the erected scaffold and the * additional language strings to the parent which will decide what to do with that. * * @return void */ public function build(); } Factory/Scaffolding/Layout/FormErector.php000064400000040337152325653710014627 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Layout; use FOF30\Model\DataModel; defined('_JEXEC') or die; /** * Erects a scaffolding XML for edit views * * @package FOF30\Factory\Scaffolding * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class FormErector extends BaseErector implements ErectorInterface { protected $addDescriptions = true; public function build() { // Get a reference to the model $model = $this->model; // Create the attributes of the form's base element $this->xml->addAttribute('validate', 'true'); // Create the fieldset sections of the form file $labelKey = $this->getLangKeyPrefix() . 'GROUP_BASIC'; $this->addString($labelKey, 'Basic'); $fieldSet = $this->xml->addChild('fieldset'); $fieldSet->addAttribute('name', 'scaffolding'); $fieldSet->addAttribute('label', $labelKey); // Get the database fields $allFields = $model->getTableFields(); // Ordering is not included if ($model->hasField('ordering')) { $fieldName = $model->getFieldAlias('ordering'); unset($allFields[$fieldName]); } // Primary key is not inclided $primaryKeyField = $model->getKeyName(); unset($allFields[$primaryKeyField]); // Get a list of "do not display" fields $doNotShow = $this->getDoNotShow(); foreach ($allFields as $fieldName => $fieldDefinition) { // Skip the fields which shouldn't be displayed if (in_array($fieldName, $doNotShow)) { continue; } // Get the lowercase field name and prepare to handle specially named fields $lowercaseFieldName = strtolower($fieldName); // access => AccessLevel if ($model->getFieldAlias('access') == $fieldName) { $this->applyAccessLevelField($model, $fieldSet, $fieldName); continue; } // tag => Tag if ($model->getFieldAlias('tag') == $fieldName) { $this->applyTagField($model, $fieldSet, $fieldName); continue; } // enabled => Published if ($model->getFieldAlias('enabled') == $fieldName) { $this->applyPublishedField($model, $fieldSet, $fieldName); continue; } // cache_handler => CacheHandler if ($lowercaseFieldName == 'cache_handler') { $this->applyCacheHandlerField($model, $fieldSet, $fieldName); continue; } // component_id => Components if ($lowercaseFieldName == 'component_id') { $this->applyComponentsField($model, $fieldSet, $fieldName); continue; } // body, introtext, fulltext, description => Editor if (in_array($lowercaseFieldName, array('body', 'introtext', 'fulltext', 'description'))) { $this->applyEditorField($model, $fieldSet, $fieldName); continue; } // email, *_email => Email if (($lowercaseFieldName == 'email') || (substr($lowercaseFieldName, -6) == 'email')) { $this->applyEmailField($model, $fieldSet, $fieldName); continue; } // image, media, *_image => Media if ( in_array($lowercaseFieldName, array('image', 'media')) || (substr($lowercaseFieldName, -6) == '_image') ) { $this->applyMediaField($model, $fieldSet, $fieldName); continue; } // language, lang, lang_id => Language if (in_array($lowercaseFieldName, array('language', 'lang', 'lang_id'))) { $this->applyLanguageField($model, $fieldSet, $fieldName); continue; } // password, passwd, pass => Password if (in_array($lowercaseFieldName, array('password', 'passwd', 'pass'))) { $this->applyPasswordField($model, $fieldSet, $fieldName); continue; } // plugin_id => Plugins if ($lowercaseFieldName == 'plugin_id') { $this->applyPluginsField($model, $fieldSet, $fieldName); continue; } // asset_id => Rules (new tab) if ($lowercaseFieldName == 'asset_id') { // Do not show the rules tab in read views if (!$this->addDescriptions) { continue; } $this->xml->addAttribute('tabbed', 1); $fieldSet->addAttribute('class', 'tab-pane active'); $rulesSet = $this->xml->addChild('fieldset'); $baseKey = $this->getLangKeyPrefix() . 'GROUP_PERMISSIONS'; $this->addString($baseKey, 'Permissions'); $this->addString($baseKey . '_DESC', 'Permissions for ' . $this->model->getContainer()->inflector->singularize($this->viewName)); $rulesSet->addAttribute('name', 'rules'); $rulesSet->addAttribute('class', 'tab-pane'); $rulesSet->addAttribute('label', $baseKey); if ($this->addDescriptions) { $rulesSet->addAttribute('description', $baseKey . '_DESC'); } $field = $rulesSet->addChild('field'); $field->addAttribute('type', 'Hidden'); $field->addAttribute('emptylabel', 'true'); $field->addAttribute('filter', 'unset'); $field->addAttribute('name', $model->getFieldAlias('asset_id')); $field = $rulesSet->addChild('field'); $field->addAttribute('name', 'rules'); $field->addAttribute('type', 'Rules'); $field->addAttribute('emptylabel', 'true'); $field->addAttribute('translate_label', 'false'); $field->addAttribute('filter', 'rules'); $field->addAttribute('validate', 'rules'); $field->addAttribute('section', 'component'); $field->addAttribute('component', $this->builder->getContainer()->componentName); continue; } // session_handler => SessionHandler if ($lowercaseFieldName == 'session_handler') { $this->applySessionHandlerField($model, $fieldSet, $fieldName); continue; } // tel, telephone, phone => Tel if (in_array($lowercaseFieldName, array('tel', 'telephone', 'phone'))) { $this->applyTelField($model, $fieldSet, $fieldName); continue; } // timezone, tz, time_zone => Timezone if (in_array($lowercaseFieldName, array('timezone', 'tz', 'time_zone'))) { $this->applyTimezoneField($model, $fieldSet, $fieldName); continue; } // url, link, href => Url if (in_array($lowercaseFieldName, array('url', 'link', 'href'))) { $this->applyUrlField($model, $fieldSet, $fieldName); continue; } // user, user_id, userid, uid => User if (in_array($lowercaseFieldName, array('user', 'user_id', 'userid', 'uid'))) { $this->applyUserField($model, $fieldSet, $fieldName); continue; } // group, group_id, groupid, gid => UserGroup if (in_array($lowercaseFieldName, array('group', 'group_id', 'groupid', 'gid'))) { $this->applyUserGroupField($model, $fieldSet, $fieldName); continue; } // Special handling for myComponent_whatever_id fields $myComponentPrefix = $this->builder->getContainer()->bareComponentName . '_'; if ((strpos($fieldName, $myComponentPrefix) === 0) && (substr($fieldName, -3) == '_id')) { $parts = explode('_', $fieldName); array_pop($parts); array_shift($parts); // myComponent_something_id => Relation or Model if (count($parts) == 1) { $foreignName = array_shift($parts); } // myComponent_something_another_id => Relation else { $foreignName1 = array_shift($parts); $foreignName1 = $this->model->getContainer()->inflector->pluralize($foreignName1); $foreignName2 = array_shift($parts); $foreignName2 = $this->model->getContainer()->inflector->pluralize($foreignName2); $modelName = $model->getName(); $modelName = $this->model->getContainer()->inflector->pluralize($modelName); $foreignName = ($foreignName1 == $modelName) ? $foreignName2 : $foreignName1; } try { if (empty($parts)) { throw new DataModel\Relation\Exception\RelationNotFound; } $model->getRelations()->getRelation($parts[0]); $this->applyRelationField($model, $fieldSet, $fieldName); continue; } catch (DataModel\Relation\Exception\RelationNotFound $e) { $foreignName = $this->model->getContainer()->inflector->pluralize($foreignName); try { $this->applyModelField($model, $fieldSet, $fieldName, $foreignName); continue; } catch (\Exception $e) { } } } // Other fields, use getFieldType $typeDef = $this->getFieldType($fieldDefinition->Type); switch ($typeDef['type']) { case 'Text': $this->applyTextField($model, $fieldSet, $fieldName); break; case 'Editor': $this->applyEditorField($model, $fieldSet, $fieldName); break; case 'Calendar': $this->applyCalendarField($model, $fieldSet, $fieldName); break; case 'Checkbox': $this->applyCheckboxField($model, $fieldSet, $fieldName); break; case 'Integer': $this->applyIntegerField($model, $fieldSet, $fieldName); break; case 'Number': $this->applyNumberField($model, $fieldSet, $fieldName); break; case 'GenericList': $this->applyGenericListField($model, $fieldSet, $fieldName, $typeDef['params']); break; } } $this->pushResults(); } private function applyFieldOfType(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName, $fieldTypeField) { $langDefs = $this->getFieldLabel($fieldName); $this->addString($langDefs['label']['key'], $langDefs['label']['value']); $this->addString($langDefs['desc']['key'], $langDefs['desc']['value']); $field = $fieldSet->addChild('field'); $field->addAttribute('name', $fieldName); $field->addAttribute('type', $fieldTypeField); $field->addAttribute('label', $langDefs['label']['key']); if ($this->addDescriptions) { $field->addAttribute('description', $langDefs['desc']['key']); } } /** * Apply an access level field * * @param \FOF30\Model\DataModel $model * @param \SimpleXMLElement $headerSet * @param \SimpleXMLElement $fieldSet * @param string $fieldName */ private function applyAccessLevelField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'AccessLevel'); } private function applyPublishedField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Published'); } private function applyCacheHandlerField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'CacheHandler'); } private function applyCalendarField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Calendar'); } private function applyCheckboxField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Checkbox'); } private function applyComponentsField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Components'); } private function applyEditorField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Editor'); } private function applyEmailField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Email'); } private function applyIntegerField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Text'); } private function applyNumberField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Number'); } private function applyMediaField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Media'); } private function applyLanguageField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Language'); } private function applyPasswordField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Password'); } private function applyPluginsField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Plugins'); } private function applySessionHandlerField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'SessionHandler'); } private function applyTelField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Tel'); } private function applyTextField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Text'); } private function applyTimezoneField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Timezone'); } private function applyUrlField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Url'); } private function applyUserField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'User'); } private function applyUserGroupField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'UserGroup'); } private function applyRelationField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Relation'); } private function applyTagField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName) { $this->applyFieldOfType($model, $fieldSet, $fieldName, 'Tag'); } private function applyModelField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName, $modelName) { // This will fail if the model is invalid, e.g. we have example_foobar_id but no #__example_foobars table. The // error will balloon up the stack and the field will be rendered as simple number field instead of a Model // field. /** @var DataModel $foreignModel */ $foreignModel = $model->getContainer()->factory->model($modelName); $value_field = $foreignModel->getKeyName(); if ($foreignModel->hasField('title')) { $value_field = $foreignModel->getFieldAlias('title'); } $langDefs = $this->getFieldLabel($fieldName); $this->addString($langDefs['label']['key'], $langDefs['label']['value']); $this->addString($langDefs['desc']['key'], $langDefs['desc']['value']); $field = $fieldSet->addChild('field'); $field->addAttribute('name', $fieldName); $field->addAttribute('type', 'Model'); $field->addAttribute('model', $modelName); $field->addAttribute('key_field', $foreignModel->getKeyName()); $field->addAttribute('value_field', $value_field); $field->addAttribute('label', $langDefs['label']['key']); if ($this->addDescriptions) { $field->addAttribute('description', $langDefs['desc']['key']); } } private function applyGenericListField(DataModel $model, \SimpleXMLElement &$fieldSet, $fieldName, $options) { $displayOptions = array(); foreach ($options as $k => $v) { $langKey = $this->builder->getContainer()->componentName . '_' . $this->viewName . '_' . $fieldName . '_OPT_' . $k; $this->addString($langKey, $v); $displayOptions[$k] = $langKey; } $langDefs = $this->getFieldLabel($fieldName); $this->addString($langDefs['label']['key'], $langDefs['label']['value']); $this->addString($langDefs['desc']['key'], $langDefs['desc']['value']); $field = $fieldSet->addChild('field'); $field->addAttribute('name', $fieldName); $field->addAttribute('type', 'GenericList'); $field->addAttribute('label', $langDefs['label']['key']); if ($this->addDescriptions) { $field->addAttribute('description', $langDefs['desc']['key']); } foreach ($displayOptions as $k => $v) { $field->addChild('option', $v)->addAttribute('value', $k); } } /** * Create a list of fields which should not be shown in the form. These are fields like created/modified/locked * user and time and other internal fields which should not be part of the form output. * * @return array */ private function getDoNotShow() { $return = array(); $checkFields = array('created_by', 'created_on', 'modified_by', 'modified_on', 'locked_by', 'locked_on'); foreach ($checkFields as $checkField) { $return[] = $this->model->getFieldAlias($checkField); } return $return; } } Factory/Scaffolding/Layout/ItemErector.php000064400000001147152325653710014616 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Layout; defined('_JEXEC') or die; /** * Erects a scaffolding XML for read views * * @package FOF30\Factory\Scaffolding * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class ItemErector extends FormErector implements ErectorInterface { public function build() { $this->addDescriptions = false; parent::build(); $this->xml->addAttribute('type', 'read'); $this->pushResults(); } } Factory/Scaffolding/Model/Builder.php000064400000004575152325653710013555 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Model; use FOF30\Container\Container; use FOF30\Factory\Magic\ModelFactory; defined('_JEXEC') or die; /** * Scaffolding Builder * * @package FOF30\Factory\Scaffolding * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Builder { /** @var \FOF30\Container\Container The container we belong to */ protected $container = null; /** * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values * * @var string */ protected $section = 'auto'; /** * Create the scaffolding builder instance * * @param \FOF30\Container\Container $c */ public function __construct(Container $c) { $this->container = $c; } /** * Make a new scaffolding document * * @param string $requestedClass The requested class, with full qualifier ie Myapp\Site\Controller\Foobar * @param string $viewName The name of the view linked to this controller * * @return bool True on success, false otherwise */ public function make($requestedClass, $viewName) { // Class already exists? Stop here if (class_exists($requestedClass)) { return true; } // I have to magically create the model class $magic = new ModelFactory($this->container); $magic->setSection($this->getSection()); $fofModel = $magic->make($viewName); /** @var ErectorInterface $erector */ $erector = new ModelErector($this, $fofModel, $viewName); $erector->setSection($this->getSection()); $erector->build(); if(!class_exists($requestedClass)) { return false; } return true; } /** * Gets the container this builder belongs to * * @return Container */ public function getContainer() { return $this->container; } /** * @return string */ public function getSection() { return $this->section; } /** * @param string $section */ public function setSection($section) { $this->section = $section; } } Factory/Scaffolding/Model/ErectorInterface.php000064400000002100152325653710015371 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Model; use FOF30\Model\DataModel; defined('_JEXEC') or die; /** * Interface ErectorInterface * @package FOF30\Factory\Scaffolding\Model * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ interface ErectorInterface { /** * Construct the erector object * * @param Builder $parent The parent builder * @param DataModel $model The model we're erecting a scaffold against * @param string $viewName The view name for this controller */ public function __construct(Builder $parent, DataModel $model, $viewName); /** * Erects a scaffold. It then uses the parent's methods to assign the erected scaffold. * * @return void */ public function build(); /** * @return string */ public function getSection(); /** * @param string $section */ public function setSection($section); } Factory/Scaffolding/Model/ModelErector.php000064400000006130152325653710014540 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\Model; use FOF30\Model\DataModel; use FOF30\Utils\ModelTypeHints; defined('_JEXEC') or die; /** * @package FOF30\Factory\Scaffolding * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class ModelErector implements ErectorInterface { /** * The Builder which called us * * @var \FOF30\Factory\Scaffolding\Controller\Builder */ protected $builder = null; /** * The Model attached to the view we're building * * @var \FOF30\Controller\DataController */ protected $model = null; /** * The name of our view * * @var string */ protected $viewName = null; /** * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values * * @var string */ protected $section = 'auto'; public function __construct(Builder $parent, DataModel $model, $viewName) { $this->builder = $parent; $this->model = $model; $this->viewName = $viewName; } public function build() { $container = $this->builder->getContainer(); $fullPath = $container->getNamespacePrefix($this->getSection()) . 'Model\\' . ucfirst($container->inflector->pluralize($this->viewName)); // Let's remove the last part and use it to create the class name $parts = explode('\\', trim($fullPath, '\\')); $className = array_pop($parts); // Now glue everything together $namespace = implode('\\', $parts); // Let's be sure that the parent class extends with a backslash $baseClass = '\\'.trim(get_class($this->model), '\\'); $code = '<?php'.PHP_EOL; $code .= PHP_EOL; $code .= 'namespace '.$namespace.';'.PHP_EOL; $code .= PHP_EOL; $code .= "defined('_JEXEC') or die;".PHP_EOL; $code .= PHP_EOL; // Let's create some type-hints for the model class $typeHints = new ModelTypeHints($this->model); $typeHints->setClassName($fullPath); $docBlock = $typeHints->getHints(); $code .= $docBlock; $code .= 'class '.$className.' extends '.$baseClass.PHP_EOL; $code .= '{'.PHP_EOL; $code .= PHP_EOL; $code .= '}'.PHP_EOL; $path = $container->backEndPath; if(in_array('Site', $parts)) { $path = $container->frontEndPath; } $path .= '/Model/'.$className.'.php'; $filesystem = $container->filesystem; $filesystem->fileWrite($path, $code); return $path; } /** * @return string */ public function getSection() { return $this->section; } /** * @param string $section */ public function setSection($section) { $this->section = $section; } } Factory/Scaffolding/View/Builder.php000064400000004764152325653710013427 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\View; use FOF30\Container\Container; use FOF30\Factory\Magic\ViewFactory; defined('_JEXEC') or die; /** * Scaffolding Builder * * @package FOF30\Factory\Scaffolding * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Builder { /** @var \FOF30\Container\Container The container we belong to */ protected $container = null; /** * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values * * @var string */ protected $section = 'auto'; /** * Create the scaffolding builder instance * * @param \FOF30\Container\Container $c */ public function __construct(Container $c) { $this->container = $c; } /** * Make a new scaffolding document * * @param string $requestedClass The requested class, with full qualifier ie Myapp\Site\Controller\Foobar * @param string $viewName The name of the view linked to this controller * @param string $viewType The type of the view linked to this controller * * @return bool True on success, false otherwise */ public function make($requestedClass, $viewName, $viewType) { // Class already exists? Stop here if (class_exists($requestedClass)) { return true; } // I have to magically create the controller class $magic = new ViewFactory($this->container); $magic->setSection($this->getSection()); $fofView = $magic->make($viewName, $viewType); /** @var ErectorInterface $erector */ $erector = new ViewErector($this, $fofView, $viewName, $viewType); $erector->setSection($this->getSection()); $erector->build(); if(!class_exists($requestedClass)) { return false; } return true; } /** * Gets the container this builder belongs to * * @return Container */ public function getContainer() { return $this->container; } /** * @return string */ public function getSection() { return $this->section; } /** * @param string $section */ public function setSection($section) { $this->section = $section; } } Factory/Scaffolding/View/ErectorInterface.php000064400000002146152325653710015255 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\View; use FOF30\View\DataView\Html; defined('_JEXEC') or die; /** * Interface ErectorInterface * @package FOF30\Factory\Scaffolding\View * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ interface ErectorInterface { /** * Construct the erector object * * @param Builder $parent The parent builder * @param Html $view The controller we're erecting a scaffold against * @param string $viewName The view name for this view * @param string $viewType The view type for this view */ public function __construct(Builder $parent, Html $view, $viewName, $viewType); /** * Erects a scaffold. It then uses the parent's methods to assign the erected scaffold. * * @return void */ public function build(); /** * @return string */ public function getSection(); /** * @param string $section */ public function setSection($section); } Factory/Scaffolding/View/ViewErector.php000064400000006026152325653710014270 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory\Scaffolding\View; use FOF30\View\DataView\Html; defined('_JEXEC') or die; /** * @package FOF30\Factory\Scaffolding * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class ViewErector implements ErectorInterface { /** * The Builder which called us * * @var \FOF30\Factory\Scaffolding\View\Builder */ protected $builder = null; /** * The Controller attached to the view we're building * * @var \FOF30\View\DataView\Html */ protected $view = null; /** * The name of our view * * @var string */ protected $viewName = null; /** * The type of our view * * @var string */ protected $viewType = null; /** * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values * * @var string */ protected $section = 'auto'; public function __construct(Builder $parent, Html $view, $viewName, $viewType) { $this->builder = $parent; $this->view = $view; $this->viewName = $viewName; $this->viewType = $viewType; } public function build() { $container = $this->builder->getContainer(); $view = ucfirst($container->inflector->pluralize($this->viewName)); $fullPath = $container->getNamespacePrefix($this->getSection()) . 'View\\' . $view.'\\'.ucfirst($this->viewType); // Let's remove the last part and use it to create the class name $parts = explode('\\', trim($fullPath, '\\')); $className = array_pop($parts); // Now glue everything together $namespace = implode('\\', $parts); // Let's be sure that the parent class extends with a backslash $baseClass = '\\'.trim(get_class($this->view), '\\'); $code = '<?php'.PHP_EOL; $code .= PHP_EOL; $code .= 'namespace '.$namespace.';'.PHP_EOL; $code .= PHP_EOL; $code .= "defined('_JEXEC') or die;".PHP_EOL; $code .= PHP_EOL; $code .= 'class '.$className.' extends '.$baseClass.PHP_EOL; $code .= '{'.PHP_EOL; $code .= PHP_EOL; $code .= '}'.PHP_EOL; $path = $container->backEndPath; if(in_array('Site', $parts)) { $path = $container->frontEndPath; } $path .= '/View/'.$view.'/'.$className.'.php'; $filesystem = $container->filesystem; $filesystem->fileWrite($path, $code); return $path; } /** * @return string */ public function getSection() { return $this->section; } /** * @param string $section */ public function setSection($section) { $this->section = $section; } } Factory/BasicFactory.php000064400000054732152325653710011261 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory; use FOF30\Container\Container; use FOF30\Controller\Controller; use FOF30\Dispatcher\Dispatcher; use FOF30\Factory\Exception\ControllerNotFound; use FOF30\Factory\Exception\DispatcherNotFound; use FOF30\Factory\Exception\FormLoadData; use FOF30\Factory\Exception\FormLoadFile; use FOF30\Factory\Exception\FormNotFound; use FOF30\Factory\Exception\ModelNotFound; use FOF30\Factory\Exception\ToolbarNotFound; use FOF30\Factory\Exception\TransparentAuthenticationNotFound; use FOF30\Factory\Exception\ViewNotFound; use FOF30\Factory\Scaffolding\Controller\Builder as ControllerBuilder; use FOF30\Factory\Scaffolding\Layout\Builder as LayoutBuilder; use FOF30\Factory\Scaffolding\Model\Builder as ModelBuilder; use FOF30\Factory\Scaffolding\View\Builder as ViewBuilder; use FOF30\Form\Form; use FOF30\Model\Model; use FOF30\Toolbar\Toolbar; use FOF30\TransparentAuthentication\TransparentAuthentication; use FOF30\View\View; use FOF30\View\ViewTemplateFinder; defined('_JEXEC') or die; /** * MVC object factory. This implements the basic functionality, i.e. creating MVC objects only if the classes exist in * the same component section (front-end, back-end) you are currently running in. The Dispatcher and Toolbar will be * created from default objects if specialised classes are not found in your application. */ class BasicFactory implements FactoryInterface { /** @var Container The container we belong to */ protected $container = null; /** @var bool Should I look for form files on the other side of the component? */ protected $formLookupInOtherSide = false; /** @var bool Should I enable view scaffolding, i.e. automatic browse, read and add/edit XML form generation when there's no other view template? */ protected $scaffolding = false; /** @var bool When enabled, FOF will commit the scaffolding results to disk. */ protected $saveScaffolding = false; /** @var bool When enabled, FOF will commit controller scaffolding results to disk. */ protected $saveControllerScaffolding = false; /** @var bool When enabled, FOF will commit model scaffolding results to disk. */ protected $saveModelScaffolding = false; /** @var bool When enabled, FOF will commit view scaffolding results to disk. */ protected $saveViewScaffolding = false; /** * Section used to build the namespace prefix. We have to pass it since in CLI scaffolding we need * to force the section we're in (ie Site or Admin). {@see \FOF30\Container\Container::getNamespacePrefix() } for valid values * * @var string */ protected $section = 'auto'; /** * Public constructor for the factory object * * @param \FOF30\Container\Container $container The container we belong to */ public function __construct(Container $container) { $this->container = $container; } /** * Create a new Controller object * * @param string $viewName The name of the view we're getting a Controller for. * @param array $config Optional MVC configuration values for the Controller object. * * @return Controller */ public function controller($viewName, array $config = array()) { $controllerClass = $this->container->getNamespacePrefix($this->getSection()) . 'Controller\\' . ucfirst($viewName); try { return $this->createController($controllerClass, $config); } catch (ControllerNotFound $e) { } $controllerClass = $this->container->getNamespacePrefix($this->getSection()) . 'Controller\\' . ucfirst($this->container->inflector->singularize($viewName)); try { $controller = $this->createController($controllerClass, $config); } catch(ControllerNotFound $e) { // Do I have to create and save the class file? If not, let's rethrow the exception if(!$this->saveControllerScaffolding) { throw $e; } $scaffolding = new ControllerBuilder($this->container); // Was the scaffolding successful? If so let's call ourself again, otherwise throw a not found exception if($scaffolding->make($controllerClass, $viewName)) { $controller = $this->controller($viewName, $config); } else { throw $e; } } return $controller; } /** * Create a new Model object * * @param string $viewName The name of the view we're getting a Model for. * @param array $config Optional MVC configuration values for the Model object. * * @return Model */ public function model($viewName, array $config = array()) { $modelClass = $this->container->getNamespacePrefix($this->getSection()) . 'Model\\' . ucfirst($viewName); try { return $this->createModel($modelClass, $config); } catch (ModelNotFound $e) { } $modelClass = $this->container->getNamespacePrefix($this->getSection()) . 'Model\\' . ucfirst($this->container->inflector->singularize($viewName)); try { $model = $this->createModel($modelClass, $config); } catch(ModelNotFound $e) { // Do I have to create and save the class file? If not, let's rethrow the exception if(!$this->saveModelScaffolding) { throw $e; } // By default model classes are plural $modelClass = $this->container->getNamespacePrefix($this->getSection()) . 'Model\\' . ucfirst($viewName); $scaffolding = new ModelBuilder($this->container); // Was the scaffolding successful? If so let's call ourself again, otherwise throw a not found exception if($scaffolding->make($modelClass, $viewName)) { $model = $this->model($viewName, $config); } else { throw $e; } } return $model; } /** * Create a new View object * * @param string $viewName The name of the view we're getting a View object for. * @param string $viewType The type of the View object. By default it's "html". * @param array $config Optional MVC configuration values for the View object. * * @return View */ public function view($viewName, $viewType = 'html', array $config = array()) { $container = $this->container; $prefix = $this->container->getNamespacePrefix($this->getSection()); $viewClass = $prefix . 'View\\' . ucfirst($viewName) . '\\' . ucfirst($viewType); try { return $this->createView($viewClass, $config); } catch (ViewNotFound $e) { } $viewClass = $prefix . 'View\\' . ucfirst($container->inflector->singularize($viewName)) . '\\' . ucfirst($viewType); try { $view = $this->createView($viewClass, $config); } catch(ViewNotFound $e) { // Do I have to create and save the class file? If not, let's rethrow the exception. Note: I can only create HTML views if(!$this->saveViewScaffolding) { throw $e; } // By default view classes are plural $viewClass = $prefix . 'View\\' . ucfirst($container->inflector->pluralize($viewName)) . '\\' . ucfirst($viewType); $scaffolding = new ViewBuilder($this->container); // Was the scaffolding successful? If so let's call ourself again, otherwise throw a not found exception if($scaffolding->make($viewClass, $viewName, $viewType)) { $view = $this->view($viewName, $viewType, $config); } else { throw $e; } } return $view; } /** * Creates a new Dispatcher * * @param array $config The configuration values for the Dispatcher object * * @return Dispatcher */ public function dispatcher(array $config = array()) { $dispatcherClass = $this->container->getNamespacePrefix($this->getSection()) . 'Dispatcher\\Dispatcher'; try { return $this->createDispatcher($dispatcherClass, $config); } catch (DispatcherNotFound $e) { // Not found. Return the default Dispatcher return new Dispatcher($this->container, $config); } } /** * Creates a new Toolbar * * @param array $config The configuration values for the Toolbar object * * @return Toolbar */ public function toolbar(array $config = array()) { $toolbarClass = $this->container->getNamespacePrefix($this->getSection()) . 'Toolbar\\Toolbar'; try { return $this->createToolbar($toolbarClass, $config); } catch (ToolbarNotFound $e) { // Not found. Return the default Toolbar return new Toolbar($this->container, $config); } } /** * Creates a new TransparentAuthentication handler * * @param array $config The configuration values for the TransparentAuthentication object * * @return TransparentAuthentication */ public function transparentAuthentication(array $config = array()) { $authClass = $this->container->getNamespacePrefix($this->getSection()) . 'TransparentAuthentication\\TransparentAuthentication'; try { return $this->createTransparentAuthentication($authClass, $config); } catch (TransparentAuthenticationNotFound $e) { // Not found. Return the default TA return new TransparentAuthentication($this->container, $config); } } /** * Creates a new Form object * * @param string $name The name of the form. * @param string $source The form source filename without path and .xml extension e.g. "form.default" OR raw XML data * @param string $viewName The name of the view you're getting the form for. * @param array $options Options to the Form object * @param bool $replace Should form fields be replaced if a field already exists with the same group/name? * @param bool $xpath An optional xpath to search for the fields. * * @return Form|null The loaded form or null if the form filename doesn't exist * * @throws \RuntimeException If the form exists but cannot be loaded * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ public function form($name, $source, $viewName, array $options = array(), $replace = true, $xpath = false) { $formClass = $this->container->getNamespacePrefix($this->getSection()) . 'Form\\Form'; try { $form = $this->createForm($formClass, $name, $options); } catch (FormNotFound $e) { // Not found. Return the default Toolbar $form = new Form($this->container, $name, $options); } // If $source looks like raw XML data, parse it directly if (strpos($source, '<form') !== false) { if ($form->load($source, $replace, $xpath) === false) { throw new FormLoadData; } return $form; } $formFileName = $this->getFormFilename($source, $viewName); if (empty($formFileName)) { if ($this->scaffolding) { $scaffolding = new LayoutBuilder($this->container); $xml = $scaffolding->make($source, $viewName); if (!is_null($xml)) { return $this->form($name, $xml, $viewName, $options, $replace, $xpath); } } return null; } if ($form->loadFile($formFileName, $replace, $xpath) === false) { throw new FormLoadFile($source); } return $form; } /** * Creates a view template finder object for a specific View * * The default configuration is: * Look for .php, .blade.php files; default layout "default"; no default subtemplate; * look only for the specified view; do NOT fall back to the default layout or subtemplate; * look for templates ONLY in site or admin, depending on where we're running from * * @param View $view The view this view template finder will be attached to * @param array $config Configuration variables for the object * * @return ViewTemplateFinder * * @throws \Exception */ public function viewFinder(View $view, array $config = array()) { // Initialise the configuration with the default values $defaultConfig = array( 'extensions' => array('.php', '.blade.php'), 'defaultLayout' => 'default', 'defaultTpl' => '', 'strictView' => true, 'strictTpl' => true, 'strictLayout' => true, 'sidePrefix' => 'auto' ); $config = array_merge($defaultConfig, $config); // Apply fof.xml overrides $appConfig = $this->container->appConfig; $key = "views." . ucfirst($view->getName()) . ".config"; $fofXmlConfig = array( 'extensions' => $appConfig->get("$key.templateExtensions", $config['extensions']), 'strictView' => $appConfig->get("$key.templateStrictView", $config['strictView']), 'strictTpl' => $appConfig->get("$key.templateStrictTpl", $config['strictTpl']), 'strictLayout' => $appConfig->get("$key.templateStrictLayout", $config['strictLayout']), 'sidePrefix' => $appConfig->get("$key.templateLocation", $config['sidePrefix']) ); $config = array_merge($config, $fofXmlConfig); // Create the new view template finder object return new ViewTemplateFinder($view, $config); } /** * Is scaffolding enabled? * * @return boolean */ public function isScaffolding() { return $this->scaffolding; } /** * Set the scaffolding status * * @param boolean $scaffolding */ public function setScaffolding($scaffolding) { $this->scaffolding = (bool) $scaffolding; } /** * Is saving the scaffolding result to disk enabled? * * @return boolean */ public function isSaveScaffolding() { return $this->saveScaffolding; } /** * Set the status of saving the scaffolding result to disk. * * @param boolean $saveScaffolding */ public function setSaveScaffolding($saveScaffolding) { $this->saveScaffolding = (bool) $saveScaffolding; } /** * Should we save controller to disk? * * @param boolean $state */ public function setSaveControllerScaffolding($state) { $this->saveControllerScaffolding = (bool) $state; } /** * Should we save controller scaffolding to disk? * * @return boolean $state */ public function isSaveControllerScaffolding() { return $this->saveControllerScaffolding; } /** * Should we save model to disk? * * @param boolean $state */ public function setSaveModelScaffolding($state) { $this->saveModelScaffolding = (bool) $state; } /** * Should we save model scaffolding to disk? * * @return boolean $state */ public function isSaveModelScaffolding() { return $this->saveModelScaffolding; } /** * Should we save view to disk? * * @param boolean $state */ public function setSaveViewScaffolding($state) { $this->saveViewScaffolding = (bool) $state; } /** * Should we save view scaffolding to disk? * * @return boolean $state */ public function isSaveViewScaffolding() { return $this->saveViewScaffolding; } /** * Creates a Controller object * * @param string $controllerClass The fully qualified class name for the Controller * @param array $config Optional MVC configuration values for the Controller object. * * @return Controller * * @throws \RuntimeException If the $controllerClass does not exist */ protected function createController($controllerClass, array $config = array()) { if (!class_exists($controllerClass)) { throw new ControllerNotFound($controllerClass); } return new $controllerClass($this->container, $config); } /** * Creates a Model object * * @param string $modelClass The fully qualified class name for the Model * @param array $config Optional MVC configuration values for the Model object. * * @return Model * * @throws \RuntimeException If the $modelClass does not exist */ protected function createModel($modelClass, array $config = array()) { if (!class_exists($modelClass)) { throw new ModelNotFound($modelClass); } return new $modelClass($this->container, $config); } /** * Creates a View object * * @param string $viewClass The fully qualified class name for the View * @param array $config Optional MVC configuration values for the View object. * * @return View * * @throws \RuntimeException If the $viewClass does not exist */ protected function createView($viewClass, array $config = array()) { if (!class_exists($viewClass)) { throw new ViewNotFound($viewClass); } return new $viewClass($this->container, $config); } /** * Creates a Toolbar object * * @param string $toolbarClass The fully qualified class name for the Toolbar * @param array $config The configuration values for the Toolbar object * * @return Toolbar * * @throws \RuntimeException If the $toolbarClass does not exist */ protected function createToolbar($toolbarClass, array $config = array()) { if (!class_exists($toolbarClass)) { throw new ToolbarNotFound($toolbarClass); } return new $toolbarClass($this->container, $config); } /** * Creates a Form object * * @param string $formClass The fully qualified class name for the Form * @param string $name The name of the form * @param array $options The options values for the Form object * * @return Toolbar * * @throws FormNotFound If the $formClass does not exist */ protected function createForm($formClass, $name, array $options = array()) { if (!class_exists($formClass)) { throw new FormNotFound($formClass); } return new $formClass($this->container, $name, $options); } /** * Creates a Dispatcher object * * @param string $dispatcherClass The fully qualified class name for the Dispatcher * @param array $config The configuration values for the Dispatcher object * * @return Dispatcher * * @throws \RuntimeException If the $dispatcherClass does not exist */ protected function createDispatcher($dispatcherClass, array $config = array()) { if (!class_exists($dispatcherClass)) { throw new DispatcherNotFound($dispatcherClass); } return new $dispatcherClass($this->container, $config); } /** * Creates a TransparentAuthentication object * * @param string $authClass The fully qualified class name for the TransparentAuthentication * @param array $config The configuration values for the TransparentAuthentication object * * @return TransparentAuthentication * * @throws \RuntimeException If the $authClass does not exist */ protected function createTransparentAuthentication($authClass, $config) { if (!class_exists($authClass)) { throw new TransparentAuthenticationNotFound($authClass); } return new $authClass($this->container, $config); } /** * Tries to find the absolute file path for an abstract form filename. For example, it may convert form.default to * /home/myuser/mysite/components/com_foobar/View/tmpl/form.default.xml. * * @param string $source The abstract form filename * @param string $viewName The name of the view we're getting the path for * * @return string|bool The fill path to the form XML file or boolean false if it's not found */ protected function getFormFilename($source, $viewName = null) { if (empty($source)) { return false; } $componentName = $this->container->componentName; if (empty($viewName)) { $viewName = $this->container->dispatcher->getController()->getView()->getName(); } $viewNameAlt = $this->container->inflector->singularize($viewName); if ($viewNameAlt == $viewName) { $viewNameAlt = $this->container->inflector->pluralize($viewName); } $componentPaths = $this->container->platform->getComponentBaseDirs($componentName); $file_root = $componentPaths['main']; $alt_file_root = $componentPaths['alt']; $template_root = $this->container->platform->getTemplateOverridePath($componentName); // Basic paths we need to always search $paths = array( // Template override $template_root . '/' . $viewName, $template_root . '/' . $viewNameAlt, // Forms inside the specialized folder for easier template overrides $file_root . '/ViewTemplates/' . $viewName, $file_root . '/ViewTemplates/' . $viewNameAlt, // This side of the component $file_root . '/View/' . $viewName . '/tmpl', $file_root . '/View/' . $viewNameAlt . '/tmpl', ); // The other side of the component if ($this->formLookupInOtherSide) { // Forms inside the specialized folder for easier template overrides $paths[] = $alt_file_root . '/ViewTemplates/' . $viewName; $paths[] = $alt_file_root . '/ViewTemplates/' . $viewNameAlt; $paths[] = $alt_file_root . '/View/' . $viewName . '/tmpl'; $paths[] = $alt_file_root . '/View/' . $viewNameAlt . '/tmpl'; } // Legacy paths, this side of the component $paths[] = $file_root . '/views/' . $viewName . '/tmpl'; $paths[] = $file_root . '/views/' . $viewNameAlt . '/tmpl'; $paths[] = $file_root . '/Model/forms'; $paths[] = $file_root . '/models/forms'; // Legacy paths, the other side of the component if ($this->formLookupInOtherSide) { $paths[] = $file_root . '/views/' . $viewName . '/tmpl'; $paths[] = $file_root . '/views/' . $viewNameAlt . '/tmpl'; $paths[] = $file_root . '/Model/forms'; $paths[] = $file_root . '/models/forms'; } $paths = array_unique($paths); // Set up the suffixes to look into $suffixes = array(); $temp_suffixes = $this->container->platform->getTemplateSuffixes(); if (!empty($temp_suffixes)) { foreach ($temp_suffixes as $suffix) { $suffixes[] = $suffix . '.xml'; } } $suffixes[] = '.xml'; // Look for all suffixes in all paths $result = false; $filesystem = $this->container->filesystem; foreach ($paths as $path) { foreach ($suffixes as $suffix) { $filename = $path . '/' . $source . $suffix; if ($filesystem->fileExists($filename)) { $result = $filename; break; } } if ($result) { break; } } return $result; } /** * @return string */ public function getSection() { return $this->section; } /** * @param string $section */ public function setSection($section) { $this->section = $section; } } Factory/FactoryInterface.php000064400000012046152325653710012130 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory; use FOF30\Container\Container; use FOF30\Controller\Controller; use FOF30\Dispatcher\Dispatcher; use FOF30\Form\Form; use FOF30\Model\Model; use FOF30\Toolbar\Toolbar; use FOF30\TransparentAuthentication\TransparentAuthentication; use FOF30\View\View; defined('_JEXEC') or die; /** * Interface for the MVC object factory */ interface FactoryInterface { /** * Public constructor for the factory object * * @param \FOF30\Container\Container $container The container we belong to */ function __construct(Container $container); /** * Create a new Controller object * * @param string $viewName The name of the view we're getting a Controller for. * @param array $config Optional MVC configuration values for the Controller object. * * @return Controller */ function controller($viewName, array $config = array()); /** * Create a new Model object * * @param string $viewName The name of the view we're getting a Model for. * @param array $config Optional MVC configuration values for the Model object. * * @return Model */ function model($viewName, array $config = array()); /** * Create a new View object * * @param string $viewName The name of the view we're getting a View object for. * @param string $viewType The type of the View object. By default it's "html". * @param array $config Optional MVC configuration values for the View object. * * @return View */ function view($viewName, $viewType = 'html', array $config = array()); /** * Creates a new Toolbar * * @param array $config The configuration values for the Toolbar object * * @return Toolbar */ function toolbar(array $config = array()); /** * Creates a new Dispatcher * * @param array $config The configuration values for the Dispatcher object * * @return Dispatcher */ function dispatcher(array $config = array()); /** * Creates a new TransparentAuthentication handler * * @param array $config The configuration values for the TransparentAuthentication object * * @return TransparentAuthentication */ function transparentAuthentication(array $config = array()); /** * Creates a new Form object * * @param string $name The name of the form. * @param string $source The form source filename without path and .xml extension e.g. "form.default" OR raw XML data * @param string $viewName The name of the view you're getting the form for. * @param array $options Options to the Form object * @param bool $replace Should form fields be replaced if a field already exists with the same group/name? * @param bool $xpath An optional xpath to search for the fields. * * @return Form|null The loaded form or null if the form filename doesn't exist * * @throws \RuntimeException If the form exists but cannot be loaded * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ function form($name, $source, $viewName, array $options = array(), $replace = true, $xpath = false); /** * Creates a view template finder object for a specific View * * @param View $view The view this view template finder will be attached to * @param array $config Configuration variables for the object * * @return mixed */ function viewFinder(View $view, array $config = array()); /** * Is scaffolding enabled? * * @return boolean */ public function isScaffolding(); /** * Set the scaffolding status * * @param boolean $scaffolding */ public function setScaffolding($scaffolding); /** * Is saving the scaffolding result to disk enabled? * * @return boolean */ public function isSaveScaffolding(); /** * Should we save controller to disk? * * @param boolean $state */ public function setSaveControllerScaffolding($state); /** * Should we save controller scaffolding to disk? * * @return boolean $state */ public function isSaveControllerScaffolding(); /** * Should we save model to disk? * * @param boolean $state */ public function setSaveModelScaffolding($state); /** * Should we save model scaffolding to disk? * * @return boolean $state */ public function isSaveModelScaffolding(); /** * Should we save view to disk? * * @param boolean $state */ public function setSaveViewScaffolding($state); /** * Should we save view scaffolding to disk? * * @return boolean $state */ public function isSaveViewScaffolding(); /** * Set the status of saving the scaffolding result to disk. * * @param boolean $saveScaffolding */ public function setSaveScaffolding($saveScaffolding); /** * @return string */ public function getSection(); /** * @param string $section */ public function setSection($section); } Factory/MagicFactory.php000064400000010752152325653710011252 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory; use FOF30\Controller\Controller; use FOF30\Factory\Exception\ControllerNotFound; use FOF30\Factory\Exception\DispatcherNotFound; use FOF30\Factory\Exception\ModelNotFound; use FOF30\Factory\Exception\TransparentAuthenticationNotFound; use FOF30\Factory\Exception\ViewNotFound; use FOF30\Factory\Magic\DispatcherFactory; use FOF30\Factory\Magic\TransparentAuthenticationFactory; use FOF30\Model\Model; use FOF30\Toolbar\Toolbar; use FOF30\TransparentAuthentication\TransparentAuthentication; use FOF30\View\View; defined('_JEXEC') or die; /** * Magic MVC object factory. This factory will "magically" create MVC objects even if the respective classes do not * exist, based on information in your fof.xml file. * * Note: This factory class will ONLY look for MVC objects in the same component section (front-end, back-end) you are * currently running in. If they are not found a new one will be created magically. */ class MagicFactory extends BasicFactory implements FactoryInterface { /** * Create a new Controller object * * @param string $viewName The name of the view we're getting a Controller for. * @param array $config Optional MVC configuration values for the Controller object. * * @return Controller */ public function controller($viewName, array $config = array()) { try { return parent::controller($viewName, $config); } catch (ControllerNotFound $e) { $magic = new Magic\ControllerFactory($this->container); return $magic->make($viewName, $config); } } /** * Create a new Model object * * @param string $viewName The name of the view we're getting a Model for. * @param array $config Optional MVC configuration values for the Model object. * * @return Model */ public function model($viewName, array $config = array()) { try { return parent::model($viewName, $config); } catch (ModelNotFound $e) { $magic = new Magic\ModelFactory($this->container); return $magic->make($viewName, $config); } } /** * Create a new View object * * @param string $viewName The name of the view we're getting a View object for. * @param string $viewType The type of the View object. By default it's "html". * @param array $config Optional MVC configuration values for the View object. * * @return View */ public function view($viewName, $viewType = 'html', array $config = array()) { try { return parent::view($viewName, $viewType, $config); } catch (ViewNotFound $e) { $magic = new Magic\ViewFactory($this->container); return $magic->make($viewName, $viewType, $config); } } /** * Creates a new Toolbar * * @param array $config The configuration values for the Toolbar object * * @return Toolbar */ public function toolbar(array $config = array()) { $appConfig = $this->container->appConfig; $defaultConfig = array( 'useConfigurationFile' => true, 'renderFrontendButtons' => in_array($appConfig->get("views.*.config.renderFrontendButtons"), array(true, 'true', 'yes', 'on', 1)), 'renderFrontendSubmenu' => in_array($appConfig->get("views.*.config.renderFrontendSubmenu"), array(true, 'true', 'yes', 'on', 1)), ); $config = array_merge($defaultConfig, $config); return parent::toolbar($config); } public function dispatcher(array $config = array()) { $dispatcherClass = $this->container->getNamespacePrefix() . 'Dispatcher\\Dispatcher'; try { return $this->createDispatcher($dispatcherClass, $config); } catch (DispatcherNotFound $e) { // Not found. Return the magically created Dispatcher $magic = new DispatcherFactory($this->container); return $magic->make($config); } } /** * Creates a new TransparentAuthentication handler * * @param array $config The configuration values for the TransparentAuthentication object * * @return TransparentAuthentication */ public function transparentAuthentication(array $config = array()) { $authClass = $this->container->getNamespacePrefix() . 'TransparentAuthentication\\TransparentAuthentication'; try { return $this->createTransparentAuthentication($authClass, $config); } catch (TransparentAuthenticationNotFound $e) { // Not found. Return the magically created TA $magic = new TransparentAuthenticationFactory($this->container); return $magic->make($config); } } } Factory/MagicSwitchFactory.php000064400000013527152325653710012437 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory; use FOF30\Controller\Controller; use FOF30\Dispatcher\Dispatcher; use FOF30\Factory\Exception\ControllerNotFound; use FOF30\Factory\Exception\DispatcherNotFound; use FOF30\Factory\Exception\ModelNotFound; use FOF30\Factory\Exception\TransparentAuthenticationNotFound; use FOF30\Factory\Exception\ViewNotFound; use FOF30\Factory\Magic\DispatcherFactory; use FOF30\Factory\Magic\TransparentAuthenticationFactory; use FOF30\Model\Model; use FOF30\Toolbar\Toolbar; use FOF30\TransparentAuthentication\TransparentAuthentication; use FOF30\View\View; defined('_JEXEC') or die; /** * Magic MVC object factory. This factory will "magically" create MVC objects even if the respective classes do not * exist, based on information in your fof.xml file. * * Note: This factory class will look for MVC objects in BOTH component sections (front-end, back-end), not just the one * you are currently running in. If no class is found a new object will be created magically. This is the same behaviour * as FOF 2.x. */ class MagicSwitchFactory extends SwitchFactory implements FactoryInterface { /** * Create a new Controller object * * @param string $viewName The name of the view we're getting a Controller for. * @param array $config Optional MVC configuration values for the Controller object. * * @return Controller */ public function controller($viewName, array $config = array()) { try { return parent::controller($viewName, $config); } catch (ControllerNotFound $e) { $magic = new Magic\ControllerFactory($this->container); // Let's pass the section override (if any) $magic->setSection($this->getSection()); return $magic->make($viewName, $config); } } /** * Create a new Model object * * @param string $viewName The name of the view we're getting a Model for. * @param array $config Optional MVC configuration values for the Model object. * * @return Model */ public function model($viewName, array $config = array()) { try { return parent::model($viewName, $config); } catch (ModelNotFound $e) { $magic = new Magic\ModelFactory($this->container); // Let's pass the section override (if any) $magic->setSection($this->getSection()); return $magic->make($viewName, $config); } } /** * Create a new View object * * @param string $viewName The name of the view we're getting a View object for. * @param string $viewType The type of the View object. By default it's "html". * @param array $config Optional MVC configuration values for the View object. * * @return View */ public function view($viewName, $viewType = 'html', array $config = array()) { try { return parent::view($viewName, $viewType, $config); } catch (ViewNotFound $e) { $magic = new Magic\ViewFactory($this->container); // Let's pass the section override (if any) $magic->setSection($this->getSection()); return $magic->make($viewName, $viewType, $config); } } /** * Creates a new Toolbar * * @param array $config The configuration values for the Toolbar object * * @return Toolbar */ public function toolbar(array $config = array()) { $appConfig = $this->container->appConfig; $defaultConfig = array( 'useConfigurationFile' => true, 'renderFrontendButtons' => in_array($appConfig->get("views.*.config.renderFrontendButtons"), array(true, 'true', 'yes', 'on', 1)), 'renderFrontendSubmenu' => in_array($appConfig->get("views.*.config.renderFrontendSubmenu"), array(true, 'true', 'yes', 'on', 1)), ); $config = array_merge($defaultConfig, $config); return parent::toolbar($config); } /** * Creates a new Dispatcher * * @param array $config The configuration values for the Dispatcher object * * @return Dispatcher */ public function dispatcher(array $config = array()) { $dispatcherClass = $this->container->getNamespacePrefix($this->getSection()) . 'Dispatcher\\Dispatcher'; try { return $this->createDispatcher($dispatcherClass, $config); } catch (DispatcherNotFound $e) { // Not found. Let's go on. } $dispatcherClass = $this->container->getNamespacePrefix('inverse') . 'Dispatcher\\Dispatcher'; try { return $this->createDispatcher($dispatcherClass, $config); } catch (DispatcherNotFound $e) { // Not found. Return the magically created Dispatcher $magic = new DispatcherFactory($this->container); // Let's pass the section override (if any) $magic->setSection($this->getSection()); return $magic->make($config); } } /** * Creates a new TransparentAuthentication * * @param array $config The configuration values for the TransparentAuthentication object * * @return TransparentAuthentication */ public function transparentAuthentication(array $config = array()) { $toolbarClass = $this->container->getNamespacePrefix($this->getSection()) . 'TransparentAuthentication\\TransparentAuthentication'; try { return $this->createTransparentAuthentication($toolbarClass, $config); } catch (TransparentAuthenticationNotFound $e) { // Not found. Let's go on. } $toolbarClass = $this->container->getNamespacePrefix('inverse') . 'TransparentAuthentication\\TransparentAuthentication'; try { return $this->createTransparentAuthentication($toolbarClass, $config); } catch (TransparentAuthenticationNotFound $e) { // Not found. Return the magically created TransparentAuthentication $magic = new TransparentAuthenticationFactory($this->container); // Let's pass the section override (if any) $magic->setSection($this->getSection()); return $magic->make($config); } } } Factory/SwitchFactory.php000064400000016616152325653710011500 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Factory; use FOF30\Container\Container; use FOF30\Controller\Controller; use FOF30\Dispatcher\Dispatcher; use FOF30\Factory\Exception\ControllerNotFound; use FOF30\Factory\Exception\DispatcherNotFound; use FOF30\Factory\Exception\ModelNotFound; use FOF30\Factory\Exception\ToolbarNotFound; use FOF30\Factory\Exception\TransparentAuthenticationNotFound; use FOF30\Factory\Exception\ViewNotFound; use FOF30\Model\Model; use FOF30\Toolbar\Toolbar; use FOF30\TransparentAuthentication\TransparentAuthentication; use FOF30\View\View; defined('_JEXEC') or die; /** * MVC object factory. This implements the advanced functionality, i.e. creating MVC objects only if the classes exist * in any component section (front-end, back-end). For example, if you're in the front-end and a Model class doesn't * exist there but does exist in the back-end then the back-end class will be returned. * * The Dispatcher and Toolbar will be created from default objects if specialised classes are not found in your application. */ class SwitchFactory extends BasicFactory implements FactoryInterface { public function __construct(Container $container) { parent::__construct($container); // Look for form files on the other side of the component $this->formLookupInOtherSide = true; } /** * Create a new Controller object * * @param string $viewName The name of the view we're getting a Controller for. * @param array $config Optional MVC configuration values for the Controller object. * * @return Controller */ public function controller($viewName, array $config = array()) { try { return parent::controller($viewName, $config); } catch (ControllerNotFound $e) { } $controllerClass = $this->container->getNamespacePrefix('inverse') . 'Controller\\' . ucfirst($viewName); try { return $this->createController($controllerClass, $config); } catch (ControllerNotFound $e) { } $controllerClass = $this->container->getNamespacePrefix('inverse') . 'Controller\\' . ucfirst($this->container->inflector->singularize($viewName)); return $this->createController($controllerClass, $config); } /** * Create a new Model object * * @param string $viewName The name of the view we're getting a Model for. * @param array $config Optional MVC configuration values for the Model object. * * @return Model */ public function model($viewName, array $config = array()) { try { return parent::model($viewName, $config); } catch (ModelNotFound $e) { } $modelClass = $this->container->getNamespacePrefix('inverse') . 'Model\\' . ucfirst($viewName); try { return $this->createModel($modelClass, $config); } catch (ModelNotFound $e) { $modelClass = $this->container->getNamespacePrefix('inverse') . 'Model\\' . ucfirst($this->container->inflector->singularize($viewName)); return $this->createModel($modelClass, $config); } } /** * Create a new View object * * @param string $viewName The name of the view we're getting a View object for. * @param string $viewType The type of the View object. By default it's "html". * @param array $config Optional MVC configuration values for the View object. * * @return View */ public function view($viewName, $viewType = 'html', array $config = array()) { try { return parent::view($viewName, $viewType, $config); } catch (ViewNotFound $e) { } $viewClass = $this->container->getNamespacePrefix('inverse') . 'View\\' . ucfirst($viewName) . '\\' . ucfirst($viewType); try { return $this->createView($viewClass, $config); } catch (ViewNotFound $e) { $viewClass = $this->container->getNamespacePrefix('inverse') . 'View\\' . ucfirst($this->container->inflector->singularize($viewName)) . '\\' . ucfirst($viewType); return $this->createView($viewClass, $config); } } /** * Creates a new Dispatcher * * @param array $config The configuration values for the Dispatcher object * * @return Dispatcher */ public function dispatcher(array $config = array()) { $dispatcherClass = $this->container->getNamespacePrefix($this->getSection()) . 'Dispatcher\\Dispatcher'; try { return $this->createDispatcher($dispatcherClass, $config); } catch (DispatcherNotFound $e) { // Not found. Let's go on. } $dispatcherClass = $this->container->getNamespacePrefix('inverse') . 'Dispatcher\\Dispatcher'; try { return $this->createDispatcher($dispatcherClass, $config); } catch (DispatcherNotFound $e) { // Not found. Return the default Dispatcher return new Dispatcher($this->container, $config); } } /** * Creates a new Toolbar * * @param array $config The configuration values for the Toolbar object * * @return Toolbar */ public function toolbar(array $config = array()) { $toolbarClass = $this->container->getNamespacePrefix($this->getSection()) . 'Toolbar\\Toolbar'; try { return $this->createToolbar($toolbarClass, $config); } catch (ToolbarNotFound $e) { // Not found. Let's go on. } $toolbarClass = $this->container->getNamespacePrefix('inverse') . 'Toolbar\\Toolbar'; try { return $this->createToolbar($toolbarClass, $config); } catch (ToolbarNotFound $e) { // Not found. Return the default Toolbar return new Toolbar($this->container, $config); } } /** * Creates a new TransparentAuthentication * * @param array $config The configuration values for the TransparentAuthentication object * * @return TransparentAuthentication */ public function transparentAuthentication(array $config = array()) { $toolbarClass = $this->container->getNamespacePrefix($this->getSection()) . 'TransparentAuthentication\\TransparentAuthentication'; try { return $this->createTransparentAuthentication($toolbarClass, $config); } catch (TransparentAuthenticationNotFound $e) { // Not found. Let's go on. } $toolbarClass = $this->container->getNamespacePrefix('inverse') . 'TransparentAuthentication\\TransparentAuthentication'; try { return $this->createTransparentAuthentication($toolbarClass, $config); } catch (TransparentAuthenticationNotFound $e) { // Not found. Return the default TransparentAuthentication return new TransparentAuthentication($this->container, $config); } } /** * Creates a view template finder object for a specific View. * * The default configuration is: * Look for .php, .blade.php files; default layout "default"; no default subtemplate; * look for both pluralised and singular views; fall back to the default layout without subtemplate; * look for templates in both site and admin * * @param View $view The view this view template finder will be attached to * @param array $config Configuration variables for the object * * @return mixed */ public function viewFinder(View $view, array $config = array()) { // Initialise the configuration with the default values $defaultConfig = array( 'extensions' => array('.php', '.blade.php'), 'defaultLayout' => 'default', 'defaultTpl' => '', 'strictView' => false, 'strictTpl' => false, 'strictLayout' => false, 'sidePrefix' => 'any' ); $config = array_merge($defaultConfig, $config); return parent::viewFinder($view, $config); } } Form/Exception/DataModelRequired.php000064400000001206152325653710013461 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Exception; use Exception; defined('_JEXEC') or die; /** * Class DataModelRequired * @package FOF30\Form\Exception * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class DataModelRequired extends \RuntimeException { public function __construct($className, $code = 0, Exception $previous = null) { $message = \JText::sprintf('LIB_FOF_FORM_ERR_DATAMODEL_REQUIRED', $className); parent::__construct($message, $code, $previous); } } Form/Exception/GetInputNotAllowed.php000064400000001205152325653710013655 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Exception; use Exception; defined('_JEXEC') or die; /** * Class GetInputNotAllowed * @package FOF30\Form\Exception * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class GetInputNotAllowed extends \LogicException { public function __construct($className, $code = 0, Exception $previous = null) { $message = \JText::sprintf('LIB_FOF_FORM_ERR_GETINPUT_NOT_ALLOWED', $className); parent::__construct($message, $code, $previous); } } Form/Exception/GetStaticNotAllowed.php000064400000001205152325653710014005 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Exception; use Exception; defined('_JEXEC') or die; /** * Class GetStaticNotAllowed * @package FOF30\Form\Exception * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class GetStaticNotAllowed extends \LogicException { public function __construct($className, $code = 0, Exception $previous = null) { $message = \JText::sprintf('LIB_FOF_FORM_ERR_GETSTATIC_NOT_ALLOWED', $className); parent::__construct($message, $code, $previous); } } Form/Exception/InvalidGroupContents.php000064400000001235152325653710014251 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Exception; use Exception; defined('_JEXEC') or die; /** * Class InvalidGroupContents * @package FOF30\Form\Exception * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class InvalidGroupContents extends \InvalidArgumentException { public function __construct($className, $code = 1, Exception $previous = null) { $message = \JText::sprintf('LIB_FOF_FORM_ERR_GETOPTIONS_INVALID_GROUP_CONTENTS', $className); parent::__construct($message, $code, $previous); } } Form/Field/AccessLevel.php000064400000010015152325653710011402 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JHtml; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('accesslevel'); /** * Form Field class for FOF * Joomla! access levels * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class AccessLevel extends \JFormFieldAccessLevel implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { /** @var array|null The select options coming from the access levels of the site */ static $defaultOptions = null; $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); $params = $this->getOptions(); if (is_null($defaultOptions)) { $db = $this->form->getContainer()->platform->getDbo(); $query = $db->getQuery(true) ->select('a.id AS value, a.title AS text') ->from('#__viewlevels AS a') ->group('a.id, a.title, a.ordering') ->order('a.ordering ASC') ->order($db->qn('title') . ' ASC'); // Get the options. $defaultOptions = $db->setQuery($query)->loadObjectList(); } $options = $defaultOptions; // If params is an array, push these options to the array if (is_array($params)) { $options = array_merge($params, $defaultOptions); } // If all levels is allowed, push it into the array. elseif ($params) { array_unshift($options, JHtml::_('select.option', '', JText::_('JOPTION_ACCESS_SHOW_ALL_LEVELS'))); } return '<span ' . ($id ? $id : '') . 'class="'. $class . '">' . htmlspecialchars(GenericList::getOptionName($options, $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } } Form/Field/Actions.php000064400000013477152325653710010630 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\Exception\DataModelRequired; use FOF30\Form\Exception\GetStaticNotAllowed; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use FOF30\Utils\StringHelper; use JHtml; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('list'); /** * Form Field class for FOF * Supports a generic list of options. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Actions extends \JFormFieldList implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the field configuration * * @return array */ protected function getConfig() { // If no custom options were defined let's figure out which ones of the // defaults we shall use... $config = array( 'published' => 1, 'unpublished' => 1, 'archived' => 0, 'trash' => 0, 'all' => 0, ); if (isset($this->element['show_published'])) { $config['published'] = StringHelper::toBool($this->element['show_published']); } if (isset($this->element['show_unpublished'])) { $config['unpublished'] = StringHelper::toBool($this->element['show_unpublished']); } if (isset($this->element['show_archived'])) { $config['archived'] = StringHelper::toBool($this->element['show_archived']); } if (isset($this->element['show_trash'])) { $config['trash'] = StringHelper::toBool($this->element['show_trash']); } if (isset($this->element['show_all'])) { $config['all'] = StringHelper::toBool($this->element['show_all']); } return $config; } /** * Method to get the field options. * * @since 2.0 * * @return array The field option objects. */ protected function getOptions() { return null; } /** * Method to get a * * @param string $enabledFieldName Name of the enabled/published field * * @return Published Field */ protected function getPublishedField($enabledFieldName) { $attributes = array( 'name' => $enabledFieldName, 'type' => 'published', ); if ($this->element['publish_up']) { $attributes['publish_up'] = (string) $this->element['publish_up']; } if ($this->element['publish_down']) { $attributes['publish_down'] = (string) $this->element['publish_down']; } $renderedAttributes = array(); foreach ($attributes as $name => $value) { if (!is_null($value)) { $renderedAttributes[] = $name . '="' . $value . '"'; } } $publishedXml = new \SimpleXMLElement('<field ' . implode(' ', $renderedAttributes) . ' />'); $publishedField = new Published($this->form); // Pass required objects to the field $publishedField->item = $this->item; $publishedField->rowid = $this->rowid; $publishedField->setup($publishedXml, $this->item->{$enabledFieldName}); return $publishedField; } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML * * @throws \LogicException */ public function getStatic() { throw new GetStaticNotAllowed(__CLASS__); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML * * @throws DataModelRequired */ public function getRepeatable() { if (!($this->item instanceof DataModel)) { throw new DataModelRequired(__CLASS__); } $config = $this->getConfig(); $html = '<div class="btn-group">'; // Render a published field if ($this->item->hasField('enabled')) { $publishedFieldName = $this->item->getFieldAlias('enabled'); if ($config['published'] || $config['unpublished']) { // Generate a FieldInterfacePublished field $publishedField = $this->getPublishedField($publishedFieldName); // Render the publish button $html .= $publishedField->getRepeatable(); } if ($config['archived']) { $archived = $this->item->getFieldValue($publishedFieldName) == 2 ? true : false; // Create dropdown items $action = $archived ? 'unarchive' : 'archive'; JHtml::_('actionsdropdown.' . $action, 'cb' . $this->rowid); } if ($config['trash']) { $trashed = $this->item->getFieldValue($publishedFieldName) == -2 ? true : false; $action = $trashed ? 'untrash' : 'trash'; JHtml::_('actionsdropdown.' . $action, 'cb' . $this->rowid); } // Render dropdown list if ($config['archived'] || $config['trash']) { $html .= JHtml::_('actionsdropdown.render', $this->item->title); } } $html .= '</div>'; return $html; } } Form/Field/Boolean.php000064400000002616152325653710010600 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use JHtml; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('list'); /** * Form Field class for FOF * Supports a drop-down list of Yes/No (boolean) answers. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Boolean extends GenericList implements FieldInterface { /** * Method to get the field options. * * Ordering is disabled by default. You can enable ordering by setting the * 'order' element in your form field. The other order values are optional. * * - order What to order. Possible values: 'name' or 'value' (default = false) * - order_dir Order direction. Possible values: 'asc' = Ascending or 'desc' = Descending (default = 'asc') * - order_case_sensitive Order case sensitive. Possible values: 'true' or 'false' (default = false) * * @return array The field option objects. * * @since Ordering is available since FOF 2.1.b2. */ protected function getOptions() { $options = parent::getOptions(); $defaultOptions = array( JHtml::_('select.option', 1, \JText::_('JYES')), JHtml::_('select.option', 0, \JText::_('JNO')), ); $options = array_merge($defaultOptions, $options); return $options; } } Form/Field/BooleanToggle.php000064400000003001152325653710011727 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use JHtml; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('list'); /** * Form Field class for FOF * Supports a drop-down list of Yes/No (boolean) answers. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class BooleanToggle extends Radio implements FieldInterface { protected function getInput() { $this->class = 'btn-group btn-group-yesno '; return parent::getInput(); } /** * Method to get the field options. * * Ordering is disabled by default. You can enable ordering by setting the * 'order' element in your form field. The other order values are optional. * * - order What to order. Possible values: 'name' or 'value' (default = false) * - order_dir Order direction. Possible values: 'asc' = Ascending or 'desc' = Descending (default = 'asc') * - order_case_sensitive Order case sensitive. Possible values: 'true' or 'false' (default = false) * * @return array The field option objects. * * @since Ordering is available since FOF 2.1.b2. */ protected function getOptions() { $options = parent::getOptions(); $defaultOptions = array( JHtml::_('select.option', 1, \JText::_('JYES')), JHtml::_('select.option', 0, \JText::_('JNO')), ); $options = array_merge($defaultOptions, $options); return $options; } } Form/Field/Button.php000064400000006007152325653710010472 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Utils\StringHelper; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('text'); /** * Form Field class for the FOF framework * Supports a button input. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Button extends Text implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return $this->getInput(); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { return $this->getInput(); } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getInput() { $this->label = ''; $allowedElement = array('button', 'a'); if (in_array($this->element['htmlelement'], $allowedElement)) { $type = $this->element['htmlelement']; } else { $type = 'button'; } $text = $this->element['text'] ? (string) $this->element['text'] : ''; $class = $this->class ? $this->class : ''; $icon = $this->element['icon'] ? '<span class="icon ' . (string) $this->element['icon'] . '"></span> ' : ''; if ($this->element['listItemTask']) { $this->onclick = "listItemTask('cb" . $this->item->getId() . "', '" . (string)$this->element['listItemTask'] . "')"; } $onclick = $this->onclick ? 'onclick="' . $this->onclick . '" ' : ''; $url = $this->element['url'] ? 'href="' . $this->parseFieldTags((string) $this->element['url']) . '" ' : ''; $title = $this->element['title'] ? 'title="' . JText::_((string) $this->element['title']) . '" ' : ''; $useValue = StringHelper::toBool((string) $this->element['use_value']); if (!$useValue) { $this->value = JText::_($text); } $html = '<' . $type . ' id="' . $this->id . '" class="btn ' . $class . '" ' . $onclick . $url . $title . '>'; $html .= $icon . htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8'); $html .= '</' . $type . '>'; return $html; } /** * Method to get the field title. * * @return string The field title. */ protected function getTitle() { return null; } } Form/Field/CacheHandler.php000064400000006050152325653710011516 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('cachehandler'); /** * Form Field class for FOF * Joomla! cache handlers * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class CacheHandler extends \JFormFieldCacheHandler implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); return '<span ' . ($id ? $id : '') . 'class="'. $class . '">' . htmlspecialchars(GenericList::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } } Form/Field/Calendar.php000064400000017641152325653710010736 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Date\Date; use FOF30\Date\DateDecorator; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JHtml; use JText; use SimpleXMLElement; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('calendar'); /** * Form Field class for the FOF framework * Supports a calendar / date field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Calendar extends \JFormFieldCalendar implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { // ATTENTION: Redirected getInput() to getStatic() case 'input': case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return $this->getCalendar('static'); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { return $this->getCalendar('repeatable'); } /** * Overridden to enable time display by default in the FOF Calendar field. This is required for backwards * compatibility: all previous Joomla! version would display the time and/or let you specify a time in the Calendar * field. Joomla! 3.7 broke this, stripping away the time by default. * * @param SimpleXMLElement $element * @param mixed $value * @param null $group * * @return bool */ public function setup(SimpleXMLElement $element, $value, $group = null) { $ret = parent::setup($element, $value, $group); // Show time by default in the FOF Calendar field $showTimeValue = (string) $this->element['showtime']; if (empty($showTimeValue)) { $this->showtime = true; } return $ret; } /** * Method to get the calendar input markup. * * @param string $display The display to render ('static' or 'repeatable') * * @return string The field input markup. * * @since 2.1.rc4 */ protected function getCalendar($display) { // Initialize some field attributes. $format = $this->format ? $this->format : '%Y-%m-%d'; $class = $this->class ? $this->class : ''; $default = $this->element['default'] ? (string) $this->element['default'] : ''; // Get some system objects. $config = $this->form->getContainer()->platform->getConfig(); $user = $this->form->getContainer()->platform->getUser(); // Check for empty date values if (empty($this->value) || $this->value == $this->form->getContainer()->platform->getDbo()->getNullDate() || $this->value == '0000-00-00') { $this->value = $default; } // Handle the special case for "now". if (strtoupper($this->value) == 'NOW') { $this->value = strftime($format); } // If a known filter is given use it. switch (strtoupper($this->filter)) { case 'SERVER_UTC': // Convert a date to UTC based on the server timezone. if ((int) $this->value) { // Get a date object based on the correct timezone. $coreObject = \JFactory::getDate($this->value, 'UTC'); $date = new DateDecorator($coreObject); $date->setTimezone(new \DateTimeZone($config->get('offset'))); // Transform the date string. $this->value = $date->format('Y-m-d H:i:s', true, false); } break; case 'USER_UTC': // Convert a date to UTC based on the user timezone. if ((int) $this->value) { // Get a date object based on the correct timezone. $coreObject = \JFactory::getDate($this->value, 'UTC'); $date = new DateDecorator($coreObject); $date->setTimezone(new \DateTimeZone($user->getParam('timezone', $config->get('offset')))); // Transform the date string. $this->value = $date->format('Y-m-d H:i:s', true, false); } break; } if ($display == 'static') { // Build the attributes array. $attributes = array(); if ($this->placeholder) { $attributes['placeholder'] = $this->placeholder; } if ($this->class) { $attributes['class'] = $this->class; } if ($this->size) { $attributes['size'] = $this->size; } if ($this->maxlength) { $attributes['maxlength'] = $this->maxlength; } if ($this->class) { $attributes['class'] = $this->class; } if ($this->readonly) { $attributes['readonly'] = 'readonly'; } if ($this->disabled) { $attributes['disabled'] = 'disabled'; } if ($this->onchange) { $attributes['onChange'] = $this->onchange; } if ($this->autocomplete) { $attributes['autocomplete'] = $this->autocomplete; } if ($this->autofocus) { $attributes['autofocus'] = $this->autofocus; } if ($this->filter) { $attributes['filter'] = $this->filter; } if ($this->today) { $attributes['todayBtn'] = $this->today; } if ($this->weeknumbers) { $attributes['weekNumbers'] = $this->weeknumbers; } if ($this->showtime) { $attributes['showTime'] = in_array(strtolower($this->showtime), ['true', '1', 'on', 'yes']); } elseif ($this->time) { $attributes['showTime'] = in_array(strtolower($this->time), ['true', '1', 'on', 'yes']); } if ($this->filltable) { $attributes['fillTable'] = in_array(strtolower($this->filltable), ['true', '1', 'on', 'yes']); } if ($this->timeformat) { $attributes['timeFormat'] = $this->timeformat; } if ($this->singleheader) { $attributes['singleHeader'] = in_array(strtolower($this->singleheader), ['true', '1', 'on', 'yes']); } if ($this->required) { $attributes['required'] = 'required'; $attributes['aria-required'] = 'true'; } // Including fallback code for HTML5 non supported browsers. JHtml::_('jquery.framework'); JHtml::_('script', 'system/html5fallback.js', false, true); if (($format == '%Y-%m-%d') && isset($attributes['showTime'])) { if ($attributes['showTime']) { $format = JText::_('DATE_FORMAT_CALENDAR_DATETIME'); } else { $format = JText::_('DATE_FORMAT_CALENDAR_DATE'); } } return JHtml::_('calendar', $this->value, $this->name, $this->id, $format, $attributes); } else { if (!$this->value && (string) $this->element['empty_replacement']) { $replacement_key = (string) $this->element['empty_replacement']; $value = \JText::_($replacement_key); } else { $date = new Date($this->value); $value = strftime($format, $date->getTimestamp()); } return '<span class="' . $this->id . ' ' . $class . '">' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '</span>'; } } } Form/Field/Callback.php000064400000007434152325653710010720 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('text'); /** * Form Field class for the FOF framework * Displays a field generated by a callback * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Callback extends \JFormField implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'input': if (empty($this->input)) { $this->input = $this->getInput(); } return $this->input; break; case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return $this->getCallbackResults(); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { return $this->getCallbackResults(); } /** * Method to get the field input markup. * * @return string The field input markup. * * @since 11.1 */ protected function getInput() { return $this->getCallbackResults(); } /** * Returns the rendered view template * * @return string */ protected function getCallbackResults() { $source_file = empty($this->element['source_file']) ? '' : (string) $this->element['source_file']; $source_class = empty($this->element['source_class']) ? '' : (string) $this->element['source_class']; $source_method = empty($this->element['source_method']) ? '' : (string) $this->element['source_method']; if (empty($source_class) || empty($source_method)) { return ''; } // Maybe we have to load a file? if (!empty($source_file)) { $source_file = $this->form->getContainer()->template->parsePath($source_file, true); if ($this->form->getContainer()->filesystem->fileExists($source_file)) { include_once $source_file; } } // Make sure the class exists if (class_exists($source_class, true)) { // ...and so does the option if (in_array($source_method, get_class_methods($source_class))) { return $source_class::$source_method(array( 'model' => $this->form->getModel(), 'form' => $this->form, 'formType' => $this->form->getAttribute('type', 'edit'), 'fieldValue' => $this->value, 'fieldElement' => $this->element, )); } } return ''; } } Form/Field/Captcha.php000064400000004263152325653710010564 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('captcha'); /** * Form Field class for the FOF framework * Supports a captcha field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Captcha extends \JFormFieldCaptcha implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return $this->getInput(); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { return $this->getInput(); } } Form/Field/Checkbox.php000064400000007315152325653710010750 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('checkbox'); /** * Form Field class for the FOF framework * A single checkbox * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Checkbox extends \JFormFieldCheckbox implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); $value = $this->element['value'] ? (string) $this->element['value'] : '1'; $disabled = $this->disabled ? ' disabled="disabled"' : ''; $required = $this->required ? ' required="required" aria-required="true"' : ''; $autofocus = $this->autofocus ? ' autofocus' : ''; $checked = $this->checked || !empty($this->value) ? ' checked' : ''; $onchange = $this->onchange ? ' onchange="' . $this->onchange . '"' : ''; $onclick = $this->onclick ? ' onclick="' . $this->onclick . '"' : ''; return '<span ' . ($id ? $id : '') . 'class="' . $class . '">' . '<input type="checkbox" name="' . $this->name . '" ' . ($id ? $id : '') . 'class="' . $this->id . ' ' . $class . '"' . ' value="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '"' . $checked . $disabled . $onclick . $onchange . $required . $autofocus . ' />' . '</span>'; } } Form/Field/Checkboxes.php000064400000006431152325653710011276 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use FOF30\Utils\StringHelper; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('checkboxes'); /** * Form Field class for FOF * Supports a list of checkbox. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Checkboxes extends \JFormFieldCheckboxes implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); $translate = StringHelper::toBool($this->element['translate']) ? true : false; $html = '<span ' . ($id ? $id : '') . 'class="' . $class . '">'; foreach ($this->value as $value) { $html .= '<span>'; if ($translate == true) { $html .= JText::_($value); } else { $html .= $value; } $html .= '</span>'; } $html .= '</span>'; return $html; } } Form/Field/Color.php000064400000005056152325653710010300 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; // no direct access defined('_JEXEC') or die('Restricted access'); \JFormHelper::loadFieldClass('color'); /** * Form Field class for the FOF framework * Color field * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Color extends \JFormFieldColor implements FieldInterface { /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * The item being rendered in a repeatable form field. * * @var DataModel */ public $item; /** * Repeatable field output. * * @var string */ protected $repeatable; /** * A monotonically increasing number, denoting the row number in a repeatable view. * * @var int */ public $rowid; /** * Static field output. * * @var string */ protected $static; /** * Method to get certain otherwise inaccessible properties from the form field * object. * * @access public * @param string $name The property name for which to the the value. * * * @since 2.0 * * @return mixed The property value or null. */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for a repeatable (grid) display, e.g. * in a view listing many item (typically a "browse" task) * * @access public * * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $class = $this->class ? $this->class : ''; $hexColor = '#' . ltrim($this->value, '#'); return '<div class="' . $this->id . ' ' . $class . '" style="width:20px; height:20px; background-color:' . $hexColor . ';">' . '</div>'; } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @access public * * * @since 2.0 * * @return string The field HTML */ public function getStatic() { // Return the joomla native control return $this->getInput(); } } Form/Field/Components.php000064400000014672152325653710011353 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('list'); /** * Form Field class for FOF * Components installed on the site * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Components extends \JFormFieldList implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Override for the list of client IDs. Comma separated list, e.g. "0,1" * * @var string */ public $client_ids = null; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.1 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.1 * * @return string The field HTML */ public function getStatic() { $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.1 * * @return string The field HTML */ public function getRepeatable() { $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); return '<span ' . ($id ? $id : '') . 'class="' . $class . '">' . htmlspecialchars(GenericList::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } /** * Get a list of all installed components and also translates them. * * The manifest_cache is used to get the extension names, since JInstaller is also * translating those names in stead of the name column. Else some of the translations * fails. * * @since 2.1 * * @return array An array of JHtml options. */ protected function getOptions() { $db = $this->form->getContainer()->platform->getDbo(); // Check for client_ids override if ($this->client_ids !== null) { $client_ids = $this->client_ids; } else { $client_ids = $this->element['client_ids']; } $client_ids = explode(',', $client_ids); // Calculate client_ids where clause foreach ($client_ids as &$client_id) { $client_id = (int) trim($client_id); $client_id = $db->q($client_id); } $query = $db->getQuery(true) ->select( array( $db->qn('name'), $db->qn('element'), $db->qn('client_id'), $db->qn('manifest_cache'), ) ) ->from($db->qn('#__extensions')) ->where($db->qn('type') . ' = ' . $db->q('component')) ->where($db->qn('client_id') . ' IN (' . implode(',', $client_ids) . ')'); $components = $db->setQuery($query)->loadObjectList('element'); // Convert to array of objects, so we can use sortObjects() // Also translate component names with JText::_() $aComponents = array(); $user = $this->form->getContainer()->platform->getUser(); foreach ($components as $component) { // Don't show components in the list where the user doesn't have access for // TODO: perhaps add an option for this if (!$user->authorise('core.manage', $component->element)) { continue; } $oData = (object) array( 'value' => $component->element, 'text' => $this->translate($component, 'component') ); $aComponents[$component->element] = $oData; } // Reorder the components array, because the alphabetical // ordering changed due to the JText::_() translation uasort( $aComponents, function ($a, $b) { return strcasecmp($a->text, $b->text); } ); return $aComponents; } /** * Translate a list of objects with JText::_(). * * @param \stdClass $item The component object * @param string $type The extension type (e.g. component) * * @since 2.1 * * @return string $text The translated name of the extension * * @see administrator/com_installer/models/extension.php */ public function translate($item, $type) { $platform = $this->form->getContainer()->platform; // Map the manifest cache to $item. This is needed to get the name from the // manifest_cache and NOT from the name column, else some JText::_() translations fails. $mData = json_decode($item->manifest_cache); if ($mData) { foreach ($mData as $key => $value) { if ($key == 'type') { // Ignore the type field continue; } $item->$key = $value; } } $lang = $platform->getLanguage(); switch ($type) { case 'component': $source = JPATH_ADMINISTRATOR . '/components/' . $item->element; $lang->load("$item->element.sys", JPATH_ADMINISTRATOR, null, false, false) || $lang->load("$item->element.sys", $source, null, false, false) || $lang->load("$item->element.sys", JPATH_ADMINISTRATOR, $lang->getDefault(), false, false) || $lang->load("$item->element.sys", $source, $lang->getDefault(), false, false); break; } $text = JText::_($item->name); return $text; } } Form/Field/Editor.php000064400000005760152325653710010452 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('editor'); /** * Form Field class for the FOF framework * An editarea field for content creation and formatted HTML display * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Editor extends \JFormFieldEditor implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); return '<div ' . ($id ? $id : '') . 'class="' . $class . '">' . $this->value . '</div>'; } } Form/Field/Email.php000064400000011631152325653710010245 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use FOF30\Utils\StringHelper; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('email'); /** * Form Field class for the FOF framework * Supports a one line text field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Email extends \JFormFieldEMail implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); $show_link = StringHelper::toBool((string) $this->element['show_link']); $empty_replacement = $this->element['empty_replacement'] ? (string) $this->element['empty_replacement'] : ''; if (!empty($empty_replacement) && empty($this->value)) { $replacement_key = (string) $this->element['empty_replacement']; $this->value = \JText::_($replacement_key); } $value = htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8'); $html = $value; if ($show_link) { if ($this->element['url']) { $link_url = $this->parseFieldTags((string) $this->element['url']); } else { $link_url = $value; } $html = '<a href="mailto:' . $link_url . '">' . $value . '</a>'; } return '<span ' . ($id ? $id : '') . 'class="' . $class . '">' . $html . '</span>'; } /** * Replace string with tags that reference fields * * @param string $text Text to process * * @return string Text with tags replace */ protected function parseFieldTags($text) { $ret = $text; // Replace [ITEM:ID] in the URL with the item's key value (usually: // the auto-incrementing numeric ID) if (is_null($this->item)) { $this->item = $this->form->getModel(); } $replace = $this->item->getId(); $ret = str_replace('[ITEM:ID]', $replace, $ret); // Replace the [ITEMID] in the URL with the current Itemid parameter $ret = str_replace('[ITEMID]', $this->form->getContainer()->input->getInt('Itemid', 0), $ret); // Replace the [TOKEN] in the URL with the Joomla! form token $ret = str_replace('[TOKEN]', \JFactory::getSession()->getFormToken(), $ret); // Replace other field variables in the URL $data = $this->item->getData(); foreach ($data as $field => $value) { // Skip non-processable values if(is_array($value) || is_object($value)) { continue; } $search = '[ITEM:' . strtoupper($field) . ']'; $ret = str_replace($search, $value, $ret); } return $ret; } } Form/Field/GenericList.php000064400000025030152325653710011424 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use FOF30\Utils\StringHelper; use JHtml; use Joomla\Utilities\ArrayHelper; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('list'); /** * Form Field class for FOF * Supports a generic list of options. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class GenericList extends \JFormFieldList implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $class = $this->class ? ' class="' . $this->class . '"' : ''; return '<span id="' . $this->id . '" ' . $class . '>' . htmlspecialchars(self::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $class = $this->class ? $this->class : ''; $link_url = $this->element['url']; if ($link_url && ($this->item instanceof DataModel)) { $link_url = $this->parseFieldTags($link_url); } else { $link_url = false; } $html = '<span class="' . $this->id . ' ' . $class . '">'; if ($link_url) { $html .= '<a href="' . $link_url . '">'; } $html .= htmlspecialchars(self::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8'); if ($link_url) { $html .= '</a>'; } $html .= '</span>'; return $html; } /** * Gets the active option's label given an array of JHtml options * * @param array $data The JHtml options to parse * @param mixed $selected The currently selected value * @param string $optKey Key name * @param string $optText Value name * @param bool $selectFirst Should I automatically select the first option? * * @return mixed The label of the currently selected option */ public static function getOptionName($data, $selected = null, $optKey = 'value', $optText = 'text', $selectFirst = true) { $ret = null; foreach ($data as $elementKey => &$element) { if (is_array($element)) { $key = $optKey === null ? $elementKey : $element[$optKey]; $text = $element[$optText]; } elseif (is_object($element)) { $key = $optKey === null ? $elementKey : $element->$optKey; $text = $element->$optText; } else { // This is a simple associative array $key = $elementKey; $text = $element; } if (is_null($ret) && $selectFirst) { $ret = $text; } elseif ($selected == $key) { $ret = $text; } } return $ret; } /** * Method to get the field options. * * Ordering is disabled by default. You can enable ordering by setting the * 'order' element in your form field. The other order values are optional. * * - order What to order. Possible values: 'name' or 'value' (default = false) * - order_dir Order direction. Possible values: 'asc' = Ascending or 'desc' = Descending (default = 'asc') * - order_case_sensitive Order case sensitive. Possible values: 'true' or 'false' (default = false) * * @return array The field option objects. * * @since Ordering is available since FOF 2.1.b2. */ protected function getOptions() { // Ordering is disabled by default for backward compatibility $order = false; // Set default order direction $order_dir = 'asc'; // Set default value for case sensitive sorting $order_case_sensitive = false; if ($this->element['order'] && $this->element['order'] !== 'false') { $order = $this->element['order']; } if ($this->element['order_dir']) { $order_dir = $this->element['order_dir']; } if ($this->element['order_case_sensitive']) { // Override default setting when the form element value is 'true' if ($this->element['order_case_sensitive'] == 'true') { $order_case_sensitive = true; } } // Create a $sortOptions array in order to apply sorting $i = 0; $sortOptions = array(); foreach ($this->element->children() as $option) { $name = JText::alt(trim((string) $option), preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname)); $sortOptions[$i] = new \stdClass; $sortOptions[$i]->option = $option; $sortOptions[$i]->value = $option['value']; $sortOptions[$i]->name = $name; $i++; } // Only order if it's set if ($order) { jimport('joomla.utilities.arrayhelper'); if (class_exists('JArrayHelper')) { \JArrayHelper::sortObjects($sortOptions, $order, $order_dir == 'asc' ? 1 : -1, $order_case_sensitive, false); } else { ArrayHelper::sortObjects($sortOptions, $order, $order_dir == 'asc' ? 1 : -1, $order_case_sensitive, false); } } // Initialise the options $options = array(); // Get the field $options foreach ($sortOptions as $sortOption) { /** @var \SimpleXMLElement $option */ $option = $sortOption->option; $name = $sortOption->name; // Only add <option /> elements. if ($option->getName() != 'option') { continue; } $tmp = JHtml::_('select.option', (string) $option['value'], $name, 'value', 'text', ((string) $option['disabled'] == 'true')); // Set some option attributes. $tmp->class = (string) $option['class']; // Set some JavaScript option attributes. $tmp->onclick = (string) $option['onclick']; // Add the option object to the result set. $options[] = $tmp; } // Do we have a class and method source for our options? $source_file = empty($this->element['source_file']) ? '' : (string) $this->element['source_file']; $source_class = empty($this->element['source_class']) ? '' : (string) $this->element['source_class']; $source_method = empty($this->element['source_method']) ? '' : (string) $this->element['source_method']; $source_key = empty($this->element['source_key']) ? '*' : (string) $this->element['source_key']; $source_value = empty($this->element['source_value']) ? '*' : (string) $this->element['source_value']; $source_translate = is_null($this->element['source_translate']) ? 'true' : (string) $this->element['source_translate']; $source_translate = StringHelper::toBool($source_translate) ? true : false; $source_format = empty($this->element['source_format']) ? '' : (string) $this->element['source_format']; if ($source_class && $source_method) { // Maybe we have to load a file? if (!empty($source_file)) { $source_file = $this->form->getContainer()->template->parsePath($source_file, true); if ($this->form->getContainer()->filesystem->fileExists($source_file)) { include_once $source_file; } } // Make sure the class exists if (class_exists($source_class, true)) { // ...and so does the option if (in_array($source_method, get_class_methods($source_class))) { // Get the data from the class if ($source_format == 'optionsobject') { $options = array_merge($options, $source_class::$source_method()); } else { // Get the data from the class $source_data = $source_class::$source_method(); // Loop through the data and prime the $options array foreach ($source_data as $k => $v) { $key = (empty($source_key) || ($source_key == '*')) ? $k : @$v[$source_key]; $value = (empty($source_value) || ($source_value == '*')) ? $v : @$v[$source_value]; if ($source_translate) { $value = JText::_($value); } $options[] = JHtml::_('select.option', $key, $value, 'value', 'text'); } } } } } reset($options); return $options; } /** * Replace string with tags that reference fields * * @param string $text Text to process * * @return string Text with tags replace */ protected function parseFieldTags($text) { $ret = $text; // Replace [ITEM:ID] in the URL with the item's key value (usually: // the auto-incrementing numeric ID) if (is_null($this->item)) { $this->item = $this->form->getModel(); } $replace = $this->item->getId(); $ret = str_replace('[ITEM:ID]', $replace, $ret); // Replace the [ITEMID] in the URL with the current Itemid parameter $ret = str_replace('[ITEMID]', $this->form->getContainer()->input->getInt('Itemid', 0), $ret); // Replace the [TOKEN] in the URL with the Joomla! form token $ret = str_replace('[TOKEN]', \JFactory::getSession()->getFormToken(), $ret); // Replace other field variables in the URL $data = $this->item->getData(); foreach ($data as $field => $value) { // Skip non-processable values if(is_array($value) || is_object($value)) { continue; } $search = '[ITEM:' . strtoupper($field) . ']'; $ret = str_replace($search, $value, $ret); } return $ret; } } Form/Field/GroupedButton.php000064400000006271152325653710012023 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('text'); /** * Form Field class for FOF * Supports a generic list of options. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class GroupedButton extends \JFormFieldText implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return $this->getInput(); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { return $this->getInput(); } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getInput() { $class = $this->class ? $this->class : ''; $html = '<div id="' . $this->id . '" class="btn-group ' . $class . '">'; /** @var \SimpleXMLElement $option */ foreach ($this->element->children() as $option) { $renderedAttributes = array(); foreach ($option->attributes() as $name => $value) { if (!is_null($value)) { $renderedAttributes[] = $name . '="' . htmlentities($value) . '"'; } } $buttonXML = new \SimpleXMLElement('<field ' . implode(' ', $renderedAttributes) . ' />'); $buttonField = new Button($this->form); // Pass required objects to the field $buttonField->item = $this->item; $buttonField->rowid = $this->rowid; $buttonField->setup($buttonXML, null); $html .= $buttonField->getRepeatable(); } $html .= '</div>'; return $html; } } Form/Field/GroupedList.php000064400000011310152325653710011451 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\Exception\InvalidGroupContents; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('groupedlist'); /** * Form Field class for FOF * Supports a generic list of options. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class GroupedList extends \JFormFieldGroupedList implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? $fieldOptions['id'] : null; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); $selected = self::getOptionName($this->getGroups(), $this->value); if (is_null($selected)) { $selected = array( 'group' => '', 'item' => '' ); } return '<span ' . ($id ? 'id="' . $id . '-group" ' : '') . 'class="fof-groupedlist-group' . $class . '">' . htmlspecialchars($selected['group'], ENT_COMPAT, 'UTF-8') . '</span>' . '<span ' . ($id ? 'id="' . $id . '-item" ' : '') . 'class="fof-groupedlist-item' . $class . '">' . htmlspecialchars($selected['item'], ENT_COMPAT, 'UTF-8') . '</span>'; } /** * Gets the active option's label given an array of JHtml options * * @param array $data The JHtml options to parse * @param mixed $selected The currently selected value * @param string $groupKey Group name * @param string $optKey Key name * @param string $optText Value name * * @return mixed The label of the currently selected option */ public static function getOptionName($data, $selected = null, $groupKey = 'items', $optKey = 'value', $optText = 'text') { if ($groupKey) {}; // Keeps phpStorm from freaking out $ret = null; foreach ($data as $dataKey => $group) { $noGroup = true; if (is_array($group) || is_object($group)) { $label = $dataKey; // If the key is a string, most likely is the title of group if(is_string($dataKey)) { $noGroup = false; } } else { throw new InvalidGroupContents(get_called_class()); } if ($noGroup) { $label = ''; } $match = GenericList::getOptionName($group, $selected, $optKey, $optText, false); if (!is_null($match)) { $ret = array( 'group' => $label, 'item' => $match ); break; } } return $ret; } } Form/Field/Hidden.php000064400000004245152325653710010414 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('hidden'); /** * Form Field class for the FOF framework * A hidden field * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Hidden extends \JFormFieldHidden implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return $this->getInput(); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { return $this->getInput(); } } Form/Field/Image.php000064400000000660152325653710010240 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; defined('_JEXEC') or die; /** * Form Field class for the FOF framework * Media selection field. This is an alias of the "media" field type. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Image extends Media { } Form/Field/ImageList.php000064400000010433152325653710011073 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JHtml; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('imagelist'); /** * Form Field class for the FOF framework * Media selection field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class ImageList extends \JFormFieldImageList implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $imgattr = array(); $alt = null; if (isset($fieldOptions['id']) && $fieldOptions['id']) { $imgattr['id'] = $fieldOptions['id']; } if ($this->class || (isset($fieldOptions['class']) && $fieldOptions['class'])) { $imgattr['class'] = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); } if ($this->element['style']) { $imgattr['style'] = (string) $this->element['style']; } if ($this->element['width']) { $imgattr['width'] = (string) $this->element['width']; } if ($this->element['height']) { $imgattr['height'] = (string) $this->element['height']; } if ($this->element['align']) { $imgattr['align'] = (string) $this->element['align']; } if ($this->element['rel']) { $imgattr['rel'] = (string) $this->element['rel']; } if ($this->element['alt']) { $alt = JText::_((string) $this->element['alt']); } if ($this->element['title']) { $imgattr['title'] = JText::_((string) $this->element['title']); } $path = (string) $this->element['directory']; $path = trim($path, '/' . DIRECTORY_SEPARATOR); $platform = $this->form->getContainer()->platform; $baseDirs = $platform->getPlatformBaseDirs(); if ($this->value && file_exists($baseDirs['root'] . '/' . $path . '/' . $this->value)) { $src = $platform->URIroot() . '/' . $path . '/' . $this->value; return JHtml::image($src, $alt, $imgattr); } // JHtml::image returns weird stuff when an empty path is provided, so let's be safe than sorry and return empty return ''; } } Form/Field/Images.php000064400000004724152325653710010430 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use JHtml; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('imagelist'); /** * Form Field class for the FOF framework * Images field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Images extends ImageList { /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); if (!is_array($this->value)) { $this->value = (array) $this->value; } $html = '<span ' . ($id ? $id : '') . 'class="'. $class . '">'; foreach ($this->value as $image) { $imgattr = array(); $alt = null; if ($class) { $imgattr['class'] = $class; } if ($this->element['style']) { $imgattr['style'] = (string) $this->element['style']; } if ($this->element['width']) { $imgattr['width'] = (string) $this->element['width']; } if ($this->element['height']) { $imgattr['height'] = (string) $this->element['height']; } if ($this->element['align']) { $imgattr['align'] = (string) $this->element['align']; } if ($this->element['rel']) { $imgattr['rel'] = (string) $this->element['rel']; } if ($this->element['alt']) { $alt = JText::_((string) $this->element['alt']); } if ($this->element['title']) { $imgattr['title'] = JText::_((string) $this->element['title']); } $path = (string) $this->element['directory']; $path = trim($path, '/' . DIRECTORY_SEPARATOR); $platform = $this->form->getContainer()->platform; $baseDirs = $platform->getPlatformBaseDirs(); if ($image && file_exists($baseDirs['root'] . '/' . $path . '/' . $image)) { $src = $platform->URIroot() . '/' . $path . '/' . $image; $html .= JHtml::image($src, $alt, $imgattr); } else { // JHtml::image returns weird stuff when an empty path is provided, so let's be safe than sorry and return empty $html .= ''; } } $html .= '</span>'; return $html; } } Form/Field/Integer.php000064400000005300152325653710010607 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('integer'); /** * Form Field class for the FOF framework * Supports a one line text field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Integer extends \JFormFieldInteger implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $class = $this->class ? ' class="' . $this->class . '"' : ''; return '<span id="' . $this->id . '" ' . $class . '>' . htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '</span>'; } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $class = $this->class ? $this->class : ''; return '<span class="' . $this->id . ' ' . $class . '">' . htmlspecialchars(GenericList::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } } Form/Field/Language.php000064400000007400152325653710010740 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JHtml; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('language'); /** * Form Field class for FOF * Available site languages * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Language extends \JFormFieldLanguage implements FieldInterface { protected static $cachedOptions = array(); /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Method to get the field options. * * @since 2.0 * * @return array The field option objects. */ protected function getOptions() { $client = (string) $this->element['client']; if ($client != 'site' && $client != 'administrator') { $client = 'site'; } if (!isset(static::$cachedOptions[$client])) { static::$cachedOptions[$client] = parent::getOptions(); } $options = array_merge(static::$cachedOptions[$client]); $noneoption = $this->element['none'] ? $this->element['none'] : null; if ($noneoption) { array_unshift($options, JHtml::_('select.option', '*', JText::_($noneoption))); } return $options; } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); return '<span ' . ($id ? $id : '') . 'class="' . $class . '">' . htmlspecialchars(GenericList::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } } Form/Field/Media.php000064400000010513152325653710010233 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JHtml; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('media'); /** * Form Field class for the FOF framework * Media selection field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Media extends \JFormFieldMedia implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $imgattr = array(); if (isset($fieldOptions['id'])) { $imgattr['id'] = $fieldOptions['id']; } if ($this->class || (isset($fieldOptions['class']) && $fieldOptions['class'])) { $imgattr['class'] = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); } if ($this->element['style']) { $imgattr['style'] = (string) $this->element['style']; } if ($this->element['width']) { $imgattr['width'] = (string) $this->element['width']; } if ($this->element['height']) { $imgattr['height'] = (string) $this->element['height']; } if ($this->element['align']) { $imgattr['align'] = (string) $this->element['align']; } if ($this->element['rel']) { $imgattr['rel'] = (string) $this->element['rel']; } if ($this->element['alt']) { $alt = JText::_((string) $this->element['alt']); } else { $alt = null; } if ($this->element['title']) { $imgattr['title'] = JText::_((string) $this->element['title']); } $directory = ''; if ($this->element['directory']) { $directory = (string) $this->element['directory']; $directory = trim($directory, '/\\') . '/'; } $imagePath = $directory . $this->value; $platform = $this->form->getContainer()->platform; $baseDirs = $platform->getPlatformBaseDirs(); if ($this->value && file_exists($baseDirs['root'] . '/' . $imagePath)) { $src = $platform->URIroot() . '/' . $imagePath; return JHtml::image($src, $alt, $imgattr); } // JHtml::image returns weird stuff when an empty path is provided, so let's be safe than sorry and return empty return ''; } } Form/Field/Model.php000064400000020602152325653710010254 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Container\Container; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use FOF30\Utils\StringHelper; use JHtml; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('list'); /** * Form Field class for FOF * Generic list from a model's results * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Model extends GenericList implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Options loaded from the model, cached for efficiency * * @var null|array */ protected static $loadedOptions = null; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { $class = $this->class ? 'class="' . $this->class . '"' : ''; return '<span id="' . $this->id . '" ' . $class . '>' . htmlspecialchars(GenericList::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { // Get field parameters $class = $this->class ? $this->class : $this->id; $format_string = $this->element['format'] ? (string) $this->element['format'] : ''; $link_url = $this->element['url'] ? (string) $this->element['url'] : ''; $empty_replacement = $this->element['empty_replacement'] ? (string) $this->element['empty_replacement'] : ''; if ($link_url && ($this->item instanceof DataModel)) { $link_url = $this->parseFieldTags($link_url); } else { $link_url = false; } if ($this->element['empty_replacement']) { $empty_replacement = (string) $this->element['empty_replacement']; } // Ask GenericList::getOptionName to not automatically select the first value $value = GenericList::getOptionName($this->getOptions(), $this->value, 'value', 'text', false); // Get the (optionally formatted) value if (!empty($empty_replacement) && empty($value)) { $value = JText::_($empty_replacement); } if (empty($format_string)) { $value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); } else { $value = sprintf($format_string, $value); } // Create the HTML $html = '<span class="' . $class . '">'; if ($link_url) { $html .= '<a href="' . $link_url . '">'; } $html .= $value; if ($link_url) { $html .= '</a>'; } $html .= '</span>'; return $html; } /** * Method to get the field options. * * @param bool $forceReset * * @return array The field option objects. */ protected function getOptions($forceReset = false) { $myFormKey = $this->form->getName() . '#$#' . (string) $this->element['model']; if ($forceReset && isset(static::$loadedOptions[$myFormKey])) { unset(static::$loadedOptions[$myFormKey]); } if (!isset(static::$loadedOptions[$myFormKey])) { $options = array(); // Initialize some field attributes. $key = $this->element['key_field'] ? (string) $this->element['key_field'] : 'value'; $value = $this->element['value_field'] ? (string) $this->element['value_field'] : (string) $this->element['name']; $valueReplace = StringHelper::toBool($this->element['parse_value']); $translate = StringHelper::toBool($this->element['translate']); $applyAccess = StringHelper::toBool($this->element['apply_access']); $modelName = (string) $this->element['model']; $nonePlaceholder = (string) $this->element['none']; $with = $this->element['with'] ? (string) $this->element['with'] : null; if (!is_null($with)) { $with = trim($with); $with = explode(',', $with); $with = array_map('trim', $with); } if (!empty($nonePlaceholder)) { $options[] = JHtml::_('select.option', null, JText::_($nonePlaceholder)); } // Explode model name into component name and prefix $componentName = $this->form->getContainer()->componentName; $mName = $modelName; if (strpos($modelName, '.') !== false) { list ($componentName, $mName) = explode('.', $mName, 2); } // Get the applicable container $container = $this->form->getContainer(); if ($componentName != $container->componentName) { $container = Container::getInstance($componentName); } /** @var DataModel $model */ $model = $container->factory->model($mName)->setIgnoreRequest(true)->savestate(false); // Get the model object if ($applyAccess) { $model->applyAccessFiltering(); } if (!is_null($with)) { $model->with($with); } // Process state variables /** @var \SimpleXMLElement $stateoption */ foreach ($this->element->children() as $stateoption) { // Only add <state /> elements. if ($stateoption->getName() != 'state') { continue; } $stateKey = (string) $stateoption['key']; $stateValue = (string) $stateoption; $model->setState($stateKey, $stateValue); } // Set the query and get the result list. $items = $model->get(true); // Build the field options. if (!empty($items)) { foreach ($items as $item) { if ($translate == true) { $options[] = JHtml::_('select.option', $item->$key, JText::_($item->$value)); } else { if ($valueReplace) { $text = $this->parseFieldTags($value, $item); } else { $text = $item->$value; } $options[] = JHtml::_('select.option', $item->$key, $text); } } } // Merge any additional options in the XML definition. $options = array_merge(parent::getOptions(), $options); static::$loadedOptions[$myFormKey] = $options; } return static::$loadedOptions[$myFormKey]; } /** * Replace string with tags that reference fields * * @param string $text Text to process * * @return string Text with tags replace */ protected function parseFieldTags($text, $item = null) { $ret = $text; if ($item) { $this->item = $item; } if (is_null($this->item)) { $this->item = $this->form->getModel(); } $replace = $this->item->getId(); $ret = str_replace('[ITEM:ID]', $replace, $ret); // Replace the [ITEMID] in the URL with the current Itemid parameter $ret = str_replace('[ITEMID]', $this->form->getContainer()->input->getInt('Itemid', 0), $ret); // Replace the [TOKEN] in the URL with the Joomla! form token $ret = str_replace('[TOKEN]', \JFactory::getSession()->getFormToken(), $ret); // Replace other field variables in the URL $data = $this->item->getData(); foreach ($data as $field => $value) { // Skip non-processable values if(is_array($value) || is_object($value)) { continue; } $search = '[ITEM:' . strtoupper($field) . ']'; $ret = str_replace($search, $value, $ret); } return $ret; } } Form/Field/Number.php000064400000006670152325653710010455 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('number'); /** * Form Field class for the FOF framework * Supports a numeric field and currency symbols. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Number extends \JFormFieldNumber implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return $this->getRepeatable(); } /** * Print out the number as requested by the attributes */ public function getRepeatable() { $currencyPos = $this->getAttribute('currency_position', false); $currencySymbol = $this->getAttribute('currency_symbol', false); // Initialise $class = $this->id; // Get field parameters if ($this->element['class']) { $class = (string) $this->element['class']; } // Start the HTML output $html = '<span class="' . $class . '">'; // Prepend currency? if ($currencyPos == 'before' && $currencySymbol) { $html .= $currencySymbol; } $number = $this->value; // Should we format the number too? $formatNumber = false; if (isset($this->element['format_number'])) { $formatNumberValue = (string)$this->element['format_number']; $formatNumber = in_array(strtolower($formatNumberValue), array('yes', 'true', 'on', 1)); } // Format the number correctly if ($formatNumber) { $numDecimals = $this->getAttribute('decimals', 2); $minNumDecimals = $this->getAttribute('min_decimals', 2); $decimalsSep = $this->getAttribute('decimals_separator', '.'); $thousandSep = $this->getAttribute('thousand_separator', ','); // Format the number $number = number_format((float)$this->value, $numDecimals, $decimalsSep, $thousandSep); } // Put it all together $html .= $number; // Append currency? if ($currencyPos == 'after' && $currencySymbol) { $html .= $currencySymbol; } // End the HTML output $html .= '</span>'; return $html; } } Form/Field/Numeric.php000064400000001273152325653710010621 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('number'); /** * Backwards compatibility field. DO NOT USE IN PHP 7.2 AND LATER. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Numeric extends Number { public function __construct($form = null) { parent::__construct($form); $this->form->getModel()->getContainer()->platform->logDeprecated("The numeric field is deprecated and may cause fatal errors in PHP 7.2 and later. Use the number field type instead."); } } Form/Field/Ordering.php000064400000016516152325653710010776 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\Exception\DataModelRequired; use FOF30\Form\Exception\GetStaticNotAllowed; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JHtml; use JText; defined('_JEXEC') or die; /** * Form Field class for FOF * Renders the row ordering interface checkbox in browse views * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Ordering extends \JFormField implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Method to get the field input markup for this field type. * * @since 2.0 * * @return string The field input markup. */ protected function getInput() { $html = array(); $attr = ''; // Initialize some field attributes. $attr .= !empty($this->class) ? ' class="' . $this->class . '"' : ''; $attr .= $this->disabled ? ' disabled' : ''; $attr .= !empty($this->size) ? ' size="' . $this->size . '"' : ''; // Initialize JavaScript field attributes. $attr .= !empty($this->onchange) ? ' onchange="' . $this->onchange . '"' : ''; $this->item = $this->form->getModel(); $keyfield = $this->item->getKeyName(); $itemId = $this->item->$keyfield; $query = $this->getQuery(); // Create a read-only list (no name) with a hidden input to store the value. if ($this->readonly) { $html[] = JHtml::_('list.ordering', '', $query, trim($attr), $this->value, $itemId ? 0 : 1); $html[] = '<input type="hidden" name="' . $this->name . '" value="' . $this->value . '"/>'; } else { // Create a regular list. $html[] = JHtml::_('list.ordering', $this->name, $query, trim($attr), $this->value, $itemId ? 0 : 1); } return implode($html); } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML * * @throws \LogicException */ public function getStatic() { throw new GetStaticNotAllowed(__CLASS__); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML * * @throws DataModelRequired */ public function getRepeatable() { if (!($this->item instanceof DataModel)) { throw new DataModelRequired(__CLASS__); } $class = isset($this->class) ? $this->class : 'input-mini'; $icon = isset($this->element['icon']) ? $this->element['icon'] : 'icon-menu'; $dnd = isset($this->element['dragndrop']) ? (string) $this->element['dragndrop'] : 'notbroken'; if (strtolower($dnd) == 'notbroken') { $dnd = !version_compare(JVERSION, '3.5.0', 'ge'); } else { $dnd = in_array(strtolower($dnd), array('1', 'true', 'yes', 'on', 'enabled'), true); } $html = ''; $view = $this->form->getView(); $ordering = $view->getLists()->order == $this->item->getFieldAlias('ordering'); if (!$view->hasAjaxOrderingSupport()) { // Ye olde Joomla! 2.5 method $disabled = $ordering ? '' : 'disabled="disabled"'; $html .= '<span>'; $html .= $view->getPagination()->orderUpIcon($this->rowid, true, 'orderup', 'Move Up', $ordering); $html .= '</span><span>'; $html .= $view->getPagination()->orderDownIcon($this->rowid, $view->getPagination()->total, true, 'orderdown', 'Move Down', $ordering); $html .= '</span>'; $html .= '<input type="text" name="order[]" size="5" value="' . $this->value . '" ' . $disabled; $html .= 'class="text-area-order" style="text-align: center" />'; } else { // The modern drag'n'drop method if ($view->getPerms()->editstate) { $disableClassName = ''; $disabledLabel = ''; $hasAjaxOrderingSupport = $view->hasAjaxOrderingSupport(); if (!$hasAjaxOrderingSupport['saveOrder']) { $disabledLabel = JText::_('JORDERINGDISABLED'); $disableClassName = 'inactive tip-top'; } $orderClass = $ordering ? 'order-enabled' : 'order-disabled'; $html .= '<div class="' . $orderClass . '">'; if ($dnd) { $html .= '<span class="sortable-handler ' . $disableClassName . '" title="' . $disabledLabel . '" rel="tooltip">'; $html .= '<span class="' . $icon . '"></span>'; $html .= '</span>'; } if ($ordering) { /** * Joomla! 3.5 and later: drag and drop reordering is broken when the ordering field is not hidden * because some random bloke submitted that code and some supposedly responsible adult with commit * rights committed it. I tried to file a PR to fix it and got the reply "can't test, won't test". * OK, then. You blindly accepted code which did the EXACT OPPOSITE of what it promised and broke * b/c. However, you won't accept the fix to your mess from someone who knows how Joomla! works and * wasted 2 hours of his time to track down your mistake, fix it and explain why your actions * resulted in a b/c break. You have to be kidding me! */ $joomla35IsBroken = version_compare(JVERSION, '3.5.0', 'ge') ? 'style="display: none"': ''; // When the developer has disabled Drag and Drop we will show the field regardless $joomla35IsBroken = $dnd ? $joomla35IsBroken : ''; $html .= '<input type="text" name="order[]" ' . $joomla35IsBroken . ' size="5" class="' . $class . ' text-area-order" value="' . $this->value . '" />'; } $html .= '</div>'; } else { $html .= '<span class="sortable-handler inactive" >'; $html .= '<i class="' . $icon . '"></i>'; $html .= '</span>'; } } return $html; } /** * Builds the query for the ordering list. * * @since 2.3.2 * * @return \JDatabaseQuery The query for the ordering form field */ protected function getQuery() { $ordering = $this->name; $title = $this->element['ordertitle'] ? (string) $this->element['ordertitle'] : $this->item->getFieldAlias('title'); $db = $this->form->getContainer()->platform->getDbo(); $query = $db->getQuery(true); $query->select(array($db->quoteName($ordering, 'value'), $db->quoteName($title, 'text'))) ->from($db->quoteName($this->item->getTableName())) ->order($ordering); return $query; } } Form/Field/Password.php000064400000006003152325653710011015 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('password'); /** * Form Field class for the FOF framework * Supports a one line text field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Password extends \JFormFieldPassword implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); return '<span ' . ($id ? $id : '') . 'class="' . $class . '">' . htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '</span>'; } } Form/Field/Plugins.php000064400000006041152325653710010636 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('plugins'); /** * Form Field class for FOF * Plugins installed on the site * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Plugins extends \JFormFieldPlugins implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); return '<span ' . ($id ? $id : '') . 'class="' . $class . '">' . htmlspecialchars(GenericList::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } } Form/Field/Published.php000064400000012255152325653710011140 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\Exception\DataModelRequired; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JHtml; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('list'); /** * Form Field class for FOF * Supports a generic list of options. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Published extends \JFormFieldList implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Method to get the field options. * * @since 2.0 * * @return array The field option objects. */ protected function getOptions() { $options = parent::getOptions(); if (!empty($options)) { return $options; } // If no custom options were defined let's figure out which ones of the // defaults we shall use... $config = array( 'published' => 1, 'unpublished' => 1, 'archived' => 0, 'trash' => 0, 'all' => 0, ); $configMap = array( 'show_published' => array('published', 1), 'show_unpublished' => array('unpublished', 1), 'show_archived' => array('archived', 0), 'show_trash' => array('trash', 0), 'show_all' => array('all', 0), ); foreach ($configMap as $attribute => $preferences) { list($configKey, $default) = $preferences; switch (strtolower($this->element[$attribute])) { case 'true': case '1': case 'yes': $config[$configKey] = true; break; case 'false': case '0': case 'no': $config[$configKey] = false; break; default: $config[$configKey] = $default; } } $stack = array(); if ($config['published']) { $stack[] = JHtml::_('select.option', '1', JText::_('JPUBLISHED')); } if ($config['unpublished']) { $stack[] = JHtml::_('select.option', '0', JText::_('JUNPUBLISHED')); } if ($config['archived']) { $stack[] = JHtml::_('select.option', '2', JText::_('JARCHIVED')); } if ($config['trash']) { $stack[] = JHtml::_('select.option', '-2', JText::_('JTRASHED')); } if ($config['all']) { $stack[] = JHtml::_('select.option', '*', JText::_('JALL')); } return $stack; } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { $class = $this->class ? ' class="' . $this->class . '"' : ''; return '<span id="' . $this->id . '" ' . $class . '>' . htmlspecialchars(GenericList::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML * * @throws DataModelRequired */ public function getRepeatable() { if (!($this->item instanceof DataModel)) { throw new DataModelRequired(__CLASS__); } $prefix = $this->element['prefix'] ? (string) $this->element['prefix'] : ''; $checkbox = $this->element['checkbox'] ? (string) $this->element['checkbox'] : 'cb'; $publish_up = $this->element['publish_up'] ? (string) $this->element['publish_up'] : null; $publish_down = $this->element['publish_down'] ? (string) $this->element['publish_down'] : null; $container = $this->form->getContainer(); $privilege = $this->element['acl_privilege'] ? $this->element['acl_privilege'] : 'core.edit.state'; $component = $this->element['acl_component'] ? $this->element['acl_component'] : $container->componentName; $component = empty($component) ? null : $component; $enabled = $container->platform->getUser()->authorise($privilege, $component); // @todo Enforce ACL checks to determine if the field should be enabled or not // Get the HTML return JHTML::_('jgrid.published', $this->value, $this->rowid, $prefix, $enabled, $checkbox, $publish_up, $publish_down); } } Form/Field/Radio.php000064400000006022152325653710010252 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('radio'); /** * Form Field class for FOF * Radio selection list * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Radio extends \JFormFieldRadio implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); return '<span ' . ($id ? $id : '') . 'class="' . $class . '">' . htmlspecialchars(GenericList::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } } Form/Field/Relation.php000064400000012315152325653710010773 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Model\DataModel; use JHtml; use JText; defined('_JEXEC') or die; /** * Form Field class for FOF * Relation list * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Relation extends GenericList { /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return $this->getRepeatable(); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { $class = $this->class ? $this->class : $this->id; $relationclass = $this->element['relationclass'] ? (string) $this->element['relationclass'] : ''; $value_field = $this->element['value_field'] ? (string) $this->element['value_field'] : 'title'; $translate = $this->element['translate'] ? (string) $this->element['translate'] : false; $link_url = $this->element['url'] ? (string) $this->element['url'] : false; if (!($link_url && $this->item instanceof DataModel)) { $link_url = false; } if ($this->element['empty_replacement']) { $empty_replacement = (string) $this->element['empty_replacement']; } $relationName = $this->form->getModel()->getContainer()->inflector->pluralize($this->name); $relations = $this->item->getRelations()->getData($relationName); $rels = array(); foreach ($relations as $relation) { $html = '<span class="' . $relationclass . '">'; if ($link_url) { $keyfield = $relation->getKeyName(); $this->_relationId = $relation->$keyfield; $url = $this->parseFieldTags($link_url); $html .= '<a href="' . $url . '">'; } if (!isset($this->valueField)) { $this->valueField = $relation->getFieldAlias($value_field); } $value = $relation->{$this->valueField}; // Get the (optionally formatted) value if (!empty($empty_replacement) && empty($value)) { $value = JText::_($empty_replacement); } if ($translate == true) { $html .= JText::_($value); } else { $html .= $value; } if ($link_url) { $html .= '</a>'; } $html .= '</span>'; $rels[] = $html; } $html = '<span class="' . $class . '">'; $html .= implode(', ', $rels); $html .= '</span>'; return $html; } /** * Method to get the field options. * * @return array The field option objects. */ protected function getOptions() { $options = array(); $this->value = array(); $value_field = $this->element['value_field'] ? (string) $this->element['value_field'] : 'title'; $name = (string) $this->element['name']; $class = $this->element['model'] ? (string) $this->element['model'] : $name; $view = $this->form->getView()->getName(); $relation = $this->form->getModel()->getContainer()->inflector->pluralize($class); /** @var DataModel $model */ $model = $this->form->getContainer()->factory->model($relation)->setIgnoreRequest(true)->savestate(false); $key = $model->getIdFieldName(); $value = $model->getFieldAlias($value_field); foreach ($model->get(true) as $option) { $options[] = JHtml::_('select.option', $option->$key, $option->$value); } if ($id = $this->form->getModel()->getId()) { $model = $this->form->getModel(); $relations = $model->$name; foreach ($relations as $item) { $this->value[] = $item->getId(); } } return $options; } /** * Replace string with tags that reference fields * * @param string $text Text to process * * @return string Text with tags replace */ protected function parseFieldTags($text) { $ret = $text; // Replace [ITEM:ID] in the URL with the item's key value (usually: // the auto-incrementing numeric ID) if (is_null($this->item)) { $this->item = $this->form->getModel(); } $replace = $this->item->getId(); $ret = str_replace('[ITEM:ID]', $replace, $ret); // Replace the [ITEMID] in the URL with the current Itemid parameter $ret = str_replace('[ITEMID]', $this->form->getContainer()->input->getInt('Itemid', 0), $ret); // Replace the [TOKEN] in the URL with the Joomla! form token $ret = str_replace('[TOKEN]', \JFactory::getSession()->getFormToken(), $ret); // Replace the [RELATION:ID] in the URL with the relation's key value $ret = str_replace('[RELATION:ID]', $this->_relationId, $ret); // Replace other field variables in the URL $data = $this->item->getData(); foreach ($data as $field => $value) { // Skip non-processable values if(is_array($value) || is_object($value)) { continue; } $search = '[ITEM:' . strtoupper($field) . ']'; $ret = str_replace($search, $value, $ret); } return $ret; } } Form/Field/RowSelect.php000064400000000610152325653710011120 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; defined('_JEXEC') or die; /** * Form Field class for FOF * Alias to RowSelect (common typo) * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class RowSelect extends SelectRow { } Form/Field/Rules.php000064400000025530152325653710010313 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JHtml; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('rules'); /** * Form Field class for FOF * Joomla! ACL Rules * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Rules extends \JFormFieldRules implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { // This field cannot provide a static display case 'static': return ''; break; // This field cannot provide a repeateable display case 'repeatable': return ''; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return ''; } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.1 * * @return string The field HTML */ public function getRepeatable() { return ''; } /** * At the timing of this writing (2013-12-03), the Joomla "rules" field is buggy. When you are * dealing with a new record it gets the default permissions from the root asset node, which * is fine for the default permissions of Joomla articles, but unsuitable for third party software. * We had to copy & paste the whole code, since we can't "inject" the correct asset id if one is * not found. Our fixes are surrounded by `FOF Library fix` remarks. * * @return string The input field's HTML for this field type */ protected function getInput() { JHtml::_('bootstrap.tooltip'); // Initialise some field attributes. $section = $this->section; $component = $this->component; $assetField = $this->assetField; // Get the actions for the asset. $actions = \JAccess::getActions($component, $section); // Iterate over the children and add to the actions. /** @var \SimpleXMLElement $el */ foreach ($this->element->children() as $el) { if ($el->getName() == 'action') { $actions[] = (object) array('name' => (string) $el['name'], 'title' => (string) $el['title'], 'description' => (string) $el['description']); } } // Get the explicit rules for this asset. if ($section == 'component') { // Need to find the asset id by the name of the component. $db = $this->form->getContainer()->platform->getDbo(); $query = $db->getQuery(true) ->select($db->quoteName('id')) ->from($db->quoteName('#__assets')) ->where($db->quoteName('name') . ' = ' . $db->quote($component)); $assetId = (int) $db->setQuery($query)->loadResult(); } else { // Find the asset id of the content. // Note that for global configuration, com_config injects asset_id = 1 into the form. $assetId = $this->form->getValue($assetField); // ==== FOF Library fix - Start ==== // If there is no assetId (let's say we are dealing with a new record), let's ask the table // to give it to us. Here you should implement your logic (ie getting default permissions from // the component or from the category) if(!$assetId) { $table = $this->form->getModel(); $assetId = $table->getAssetParentId(); } // ==== FOF Library fix - End ==== } // Full width format. // Get the rules for just this asset (non-recursive). $assetRules = \JAccess::getAssetRules($assetId); // Get the available user groups. $groups = $this->getUserGroups(); // Prepare output $html = array(); // Description $html[] = '<p class="rule-desc">' . JText::_('JLIB_RULES_SETTINGS_DESC') . '</p>'; // Begin tabs $html[] = '<div id="permissions-sliders" class="tabbable tabs-left">'; // Building tab nav $html[] = '<ul class="nav nav-tabs">'; foreach ($groups as $group) { // Initial Active Tab $active = ""; if ($group->value == 1) { $active = "active"; } $html[] = '<li class="' . $active . '">'; $html[] = '<a href="#permission-' . $group->value . '" data-toggle="tab">'; $html[] = str_repeat('<span class="level">–</span> ', $curLevel = $group->level) . $group->text; $html[] = '</a>'; $html[] = '</li>'; } $html[] = '</ul>'; $html[] = '<div class="tab-content">'; // Start a row for each user group. foreach ($groups as $group) { // Initial Active Pane $active = ""; if ($group->value == 1) { $active = " active"; } $html[] = '<div class="tab-pane' . $active . '" id="permission-' . $group->value . '">'; $html[] = '<table class="table table-striped">'; $html[] = '<thead>'; $html[] = '<tr>'; $html[] = '<th class="actions" id="actions-th' . $group->value . '">'; $html[] = '<span class="acl-action">' . JText::_('JLIB_RULES_ACTION') . '</span>'; $html[] = '</th>'; $html[] = '<th class="settings" id="settings-th' . $group->value . '">'; $html[] = '<span class="acl-action">' . JText::_('JLIB_RULES_SELECT_SETTING') . '</span>'; $html[] = '</th>'; // The calculated setting is not shown for the root group of global configuration. $canCalculateSettings = ($group->parent_id || !empty($component)); if ($canCalculateSettings) { $html[] = '<th id="aclactionth' . $group->value . '">'; $html[] = '<span class="acl-action">' . JText::_('JLIB_RULES_CALCULATED_SETTING') . '</span>'; $html[] = '</th>'; } $html[] = '</tr>'; $html[] = '</thead>'; $html[] = '<tbody>'; foreach ($actions as $action) { $html[] = '<tr>'; $html[] = '<td headers="actions-th' . $group->value . '">'; $html[] = '<label for="' . $this->id . '_' . $action->name . '_' . $group->value . '" class="hasTooltip" title="' . htmlspecialchars(JText::_($action->title) . ' ' . JText::_($action->description), ENT_COMPAT, 'UTF-8') . '">'; $html[] = JText::_($action->title); $html[] = '</label>'; $html[] = '</td>'; $html[] = '<td headers="settings-th' . $group->value . '">'; $html[] = '<select class="input-small" name="' . $this->name . '[' . $action->name . '][' . $group->value . ']" id="' . $this->id . '_' . $action->name . '_' . $group->value . '" title="' . JText::sprintf('JLIB_RULES_SELECT_ALLOW_DENY_GROUP', JText::_($action->title), trim($group->text)) . '">'; $inheritedRule = \JAccess::checkGroup($group->value, $action->name, $assetId); // Get the actual setting for the action for this group. $assetRule = $assetRules->allow($action->name, $group->value); // Build the dropdowns for the permissions sliders // The parent group has "Not Set", all children can rightly "Inherit" from that. $html[] = '<option value=""' . ($assetRule === null ? ' selected="selected"' : '') . '>' . JText::_(empty($group->parent_id) && empty($component) ? 'JLIB_RULES_NOT_SET' : 'JLIB_RULES_INHERITED') . '</option>'; $html[] = '<option value="1"' . ($assetRule === true ? ' selected="selected"' : '') . '>' . JText::_('JLIB_RULES_ALLOWED') . '</option>'; $html[] = '<option value="0"' . ($assetRule === false ? ' selected="selected"' : '') . '>' . JText::_('JLIB_RULES_DENIED') . '</option>'; $html[] = '</select>  '; // If this asset's rule is allowed, but the inherited rule is deny, we have a conflict. if (($assetRule === true) && ($inheritedRule === false)) { $html[] = JText::_('JLIB_RULES_CONFLICT'); } $html[] = '</td>'; // Build the Calculated Settings column. // The inherited settings column is not displayed for the root group in global configuration. if ($canCalculateSettings) { $html[] = '<td headers="aclactionth' . $group->value . '">'; // This is where we show the current effective settings considering currrent group, path and cascade. // Check whether this is a component or global. Change the text slightly. if (\JAccess::checkGroup($group->value, 'core.admin', $assetId) !== true) { if ($inheritedRule === null) { $html[] = '<span class="label label-important">' . JText::_('JLIB_RULES_NOT_ALLOWED') . '</span>'; } elseif ($inheritedRule === true) { $html[] = '<span class="label label-success">' . JText::_('JLIB_RULES_ALLOWED') . '</span>'; } elseif ($inheritedRule === false) { if ($assetRule === false) { $html[] = '<span class="label label-important">' . JText::_('JLIB_RULES_NOT_ALLOWED') . '</span>'; } else { $html[] = '<span class="label"><i class="icon-lock icon-white"></i> ' . JText::_('JLIB_RULES_NOT_ALLOWED_LOCKED') . '</span>'; } } } elseif (!empty($component)) { $html[] = '<span class="label label-success"><i class="icon-lock icon-white"></i> ' . JText::_('JLIB_RULES_ALLOWED_ADMIN') . '</span>'; } else { // Special handling for groups that have global admin because they can't be denied. // The admin rights can be changed. if ($action->name === 'core.admin') { $html[] = '<span class="label label-success">' . JText::_('JLIB_RULES_ALLOWED') . '</span>'; } elseif ($inheritedRule === false) { // Other actions cannot be changed. $html[] = '<span class="label label-important"><i class="icon-lock icon-white"></i> ' . JText::_('JLIB_RULES_NOT_ALLOWED_ADMIN_CONFLICT') . '</span>'; } else { $html[] = '<span class="label label-success"><i class="icon-lock icon-white"></i> ' . JText::_('JLIB_RULES_ALLOWED_ADMIN') . '</span>'; } } $html[] = '</td>'; } $html[] = '</tr>'; } $html[] = '</tbody>'; $html[] = '</table></div>'; } $html[] = '</div></div>'; $html[] = '<div class="alert">'; if ($section == 'component' || $section == null) { $html[] = JText::_('JLIB_RULES_SETTING_NOTES'); } else { $html[] = JText::_('JLIB_RULES_SETTING_NOTES_ITEM'); } $html[] = '</div>'; return implode("\n", $html); } } Form/Field/SelectRow.php000064400000006620152325653710011127 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\Exception\DataModelRequired; use FOF30\Form\Exception\GetInputNotAllowed; use FOF30\Form\Exception\GetStaticNotAllowed; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JHtml; defined('_JEXEC') or die; /** * Form Field class for FOF * Renders the checkbox in browse views which allows you to select rows * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class SelectRow extends \JFormField implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Method to get the field input markup for this field type. * * @since 2.0 * * @return string The field input markup. * * @throws GetInputNotAllowed */ protected function getInput() { throw new GetInputNotAllowed(__CLASS__); } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML * * @throws \LogicException */ public function getStatic() { throw new GetStaticNotAllowed(__CLASS__); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML * * @throws DataModelRequired */ public function getRepeatable() { // Should I support checked-out elements? $checkoutSupport = false; if (isset($this->element['checkout'])) { $checkoutSupportValue = (string)$this->element['checkout']; $checkoutSupport = in_array(strtolower($checkoutSupportValue), array('yes', 'true', 'on', 1)); } if (!($this->item instanceof DataModel)) { throw new DataModelRequired(__CLASS__); } // Is this record checked out? $userId = $this->form->getContainer()->platform->getUser()->get('id', 0); $checked_out = false; if ($checkoutSupport) { $checked_out = $this->item->isLocked($userId); } // Get the key id for this record $key_field = $this->item->getKeyName(); $key_id = $this->item->$key_field; // Get the HTML return JHtml::_('grid.id', $this->rowid, $key_id, $checked_out); } } Form/Field/SessionHandler.php000064400000006062152325653710012141 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('sessionhandler'); /** * Form Field class for FOF * Joomla! session handlers * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class SessionHandler extends \JFormFieldSessionHandler implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); return '<span ' . ($id ? $id : '') . 'class="' . $class . '">' . htmlspecialchars(GenericList::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } } Form/Field/Spacer.php000064400000004270152325653710010434 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('spacer'); /** * Form Field class for the FOF framework * Spacer used between form elements * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Spacer extends \JFormFieldSpacer implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return $this->getInput(); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { return $this->getInput(); } } Form/Field/Sql.php000064400000006056152325653710007762 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('sql'); /** * Form Field class for FOF * Radio selection listGeneric list from an SQL statement * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Sql extends \JFormFieldSql implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); return '<span ' . ($id ? $id : '') . 'class="' . $class . '">' . htmlspecialchars(GenericList::getOptionName($this->getOptions(), $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } } Form/Field/Tag.php000064400000010253152325653710007730 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('tag'); /** * Form Field class for FOF * Tag Fields * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Tag extends \JFormFieldTag implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.1 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); $front_link = $this->element['front_link'] ? (string) $this->element['front_link'] : false; $translate = $this->element['translate'] ? (string) $this->element['translate'] : false; $tagIds = is_array($this->value) ? implode(',', $this->value) : $this->value; if (!$this->item instanceof DataModel) { $this->item = $this->form->getModel(); } if ($tagIds && $this->item instanceof DataModel) { $db = $this->form->getContainer()->platform->getDbo(); $query = $db->getQuery(true) ->select(array($db->quoteName('id'), $db->quoteName('title'))) ->from($db->quoteName('#__tags')) ->where($db->quoteName('id') . ' IN (' . $tagIds . ')'); $query->order($db->quoteName('title')); $db->setQuery($query); $tags = $db->loadObjectList(); $html = ''; foreach ($tags as $tag) { $html .= '<span>'; if ($front_link) { \JLoader::register('TagsHelperRoute', \JPATH_SITE . '/components/com_tags/helpers/route.php'); $html .= '<a href="' . \JRoute::_(\TagsHelperRoute::getTagRoute($tag->id)) . '">'; } if ($translate == true) { $html .= \JText::_($tag->title); } else { $html .= $tag->title; } if ($front_link) { $html .= '</a>'; } $html .= '</span>'; } } return '<span ' . ($id ? $id : '') . 'class="' . $class . '">' . $html . '</span>'; } } Form/Field/Tel.php000064400000011664152325653710007750 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('tel'); /** * Form Field class for the FOF framework * Supports a URL text field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Tel extends \JFormFieldTel implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); $show_link = in_array((string) $this->element['show_link'], array('true', '1', 'on', 'yes')); $empty_replacement = $this->element['empty_replacement'] ? (string) $this->element['empty_replacement'] : ''; if (!empty($empty_replacement) && empty($this->value)) { $this->value = JText::_($empty_replacement); } $value = htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8'); $html = $value; if ($show_link) { if ($this->element['url']) { $link_url = $this->parseFieldTags((string) $this->element['url']); } else { $link_url = $value; } $html = '<a href="tel:' . $link_url . '">' . $value . '</a>'; } return '<span ' . ($id ? $id : '') . 'class="' . $class . '"">' . $html . '</span>'; } /** * Replace string with tags that reference fields * * @param string $text Text to process * * @return string Text with tags replace */ protected function parseFieldTags($text) { $ret = $text; // Replace [ITEM:ID] in the URL with the item's key value (usually: // the auto-incrementing numeric ID) if (is_null($this->item)) { $this->item = $this->form->getModel(); } $replace = $this->item->getId(); $ret = str_replace('[ITEM:ID]', $replace, $ret); // Replace the [ITEMID] in the URL with the current Itemid parameter $ret = str_replace('[ITEMID]', $this->form->getContainer()->input->getInt('Itemid', 0), $ret); // Replace the [TOKEN] in the URL with the Joomla! form token $ret = str_replace('[TOKEN]', \JFactory::getSession()->getFormToken(), $ret); // Replace other field variables in the URL $data = $this->item->getData(); foreach ($data as $field => $value) { // Skip non-processable values if(is_array($value) || is_object($value)) { continue; } $search = '[ITEM:' . strtoupper($field) . ']'; $ret = str_replace($search, $value, $ret); } return $ret; } } Form/Field/Text.php000064400000017356152325653710010154 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('text'); /** * Form Field class for the FOF framework * Supports a one line text field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Text extends \JFormFieldText implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (is_array($this->value)) { $this->value = empty($this->value) ? '' : print_r($this->value, true); } if (isset($this->element['legacy'])) { return $this->getInput(); } $class = $this->class ? ' class="' . $this->class . '"' : ''; $empty_replacement = $this->element['empty_replacement'] ? (string) $this->element['empty_replacement'] : ''; if (!empty($empty_replacement) && empty($this->value)) { $this->value = JText::_($empty_replacement); } return '<span id="' . $this->id . '" ' . $class . '>' . htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8') . '</span>'; } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (is_array($this->value)) { $this->value = print_r($this->value, true); } if (isset($this->element['legacy'])) { return $this->getInput(); } // Should I support checked-out elements? $checkoutSupport = false; if (isset($this->element['checkout'])) { $checkoutSupportValue = (string)$this->element['checkout']; $checkoutSupport = in_array(strtolower($checkoutSupportValue), array('yes', 'true', 'on', 1)); } // Initialise $class = $this->class ? $this->class : $this->id; $format_string = $this->element['format'] ? (string) $this->element['format'] : ''; $format_if_not_empty = in_array((string) $this->element['format_if_not_empty'], array('true', '1', 'on', 'yes')); $parse_value = in_array((string) $this->element['parse_value'], array('true', '1', 'on', 'yes')); $link_url = $this->element['url'] ? (string) $this->element['url'] : ''; $empty_replacement = $this->element['empty_replacement'] ? (string) $this->element['empty_replacement'] : ''; $format_source_file = empty($this->element['format_source_file']) ? '' : (string) $this->element['format_source_file']; $format_source_class = empty($this->element['format_source_class']) ? '' : (string) $this->element['format_source_class']; $format_source_method = empty($this->element['format_source_method']) ? '' : (string) $this->element['format_source_method']; if ($link_url && ($this->item instanceof DataModel)) { $link_url = $this->parseFieldTags($link_url); } else { $link_url = false; } // Get the (optionally formatted) value $value = $this->value; if (!empty($empty_replacement) && empty($this->value)) { $value = JText::_($empty_replacement); } if ($parse_value) { $value = $this->parseFieldTags($value); } if (!empty($format_string) && (!$format_if_not_empty || ($format_if_not_empty && !empty($this->value)))) { $format_string = $this->parseFieldTags($format_string); $value = sprintf($format_string, $value); } elseif ($format_source_class && $format_source_method) { // Maybe we have to load a file? if (!empty($format_source_file)) { $format_source_file = $this->form->getContainer()->template->parsePath($format_source_file, true); if ($this->form->getContainer()->filesystem->fileExists($format_source_file)) { include_once $format_source_file; } } // Make sure the class and method exist if (class_exists($format_source_class, true) && in_array($format_source_method, get_class_methods($format_source_class))) { $value = $format_source_class::$format_source_method($value); $value = $this->parseFieldTags($value); } else { $value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); } } else { $value = htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); } // Create the HTML $html = '<span class="' . $class . '">'; $userId = $this->form->getContainer()->platform->getUser()->id; if ($checkoutSupport && $this->item->isLocked($userId)) { $key_field = $this->item->getKeyName(); $key_id = $this->item->$key_field; $lockedBy = ''; $lockedOn = ''; if ($this->item->hasField('locked_by')) { $lockedUser = $this->form->getContainer()->platform->getUser($this->item->getFieldValue('locked_by')); $lockedBy = $lockedUser->name . ' (' . $lockedUser->username . ')'; } if ($this->item->hasField('locked_on')) { $lockedOn = $this->item->getFieldValue('locked_on'); } $html .= \JHtml::_('jgrid.checkedout', $key_id, $lockedBy, $lockedOn, '', true); } if ($link_url) { $html .= '<a href="' . $link_url . '">'; } $html .= $value; if ($link_url) { $html .= '</a>'; } $html .= '</span>'; return $html; } /** * Replace string with tags that reference fields * * @param string $text Text to process * * @return string Text with tags replace */ protected function parseFieldTags($text) { $ret = $text; // Replace [ITEM:ID] in the URL with the item's key value (usually: // the auto-incrementing numeric ID) if (is_null($this->item)) { $this->item = $this->form->getModel(); } $replace = $this->item->getId(); $ret = str_replace('[ITEM:ID]', $replace, $ret); // Replace the [ITEMID] in the URL with the current Itemid parameter $ret = str_replace('[ITEMID]', $this->form->getContainer()->input->getInt('Itemid', 0), $ret); // Replace the [TOKEN] in the URL with the Joomla! form token $ret = str_replace('[TOKEN]', \JFactory::getSession()->getFormToken(), $ret); // Replace other field variables in the URL $data = $this->item->getData(); foreach ($data as $field => $value) { // Skip non-processable values if(is_array($value) || is_object($value)) { continue; } $search = '[ITEM:' . strtoupper($field) . ']'; $ret = str_replace($search, $value, $ret); } return $ret; } } Form/Field/TextArea.php000064400000005775152325653710010747 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('textarea'); /** * Form Field class for the FOF framework * Supports a text area * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class TextArea extends \JFormFieldTextarea implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); return '<div ' . ($id ? $id : '') . 'class="' . $class . '">' . htmlspecialchars(nl2br($this->value), ENT_COMPAT, 'UTF-8') . '</div>'; } } Form/Field/Timezone.php000064400000006601152325653710011011 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('timezone'); /** * Form Field class for FOF * Supports a generic list of options. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Timezone extends \JFormFieldTimezone implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? $fieldOptions['id'] : null; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); $selected = GroupedList::getOptionName($this->getGroups(), $this->value); if (is_null($selected)) { $selected = array( 'group' => '', 'item' => '' ); } return '<span ' . ($id ? 'id="' . $id . '-group" ' : '') . 'class="fof-groupedlist-group ' . $class . '>' . htmlspecialchars($selected['group'], ENT_COMPAT, 'UTF-8') . '</span>' . '<span ' . ($id ? 'id="' . $id . '-item" ' : '') . 'class="fof-groupedlist-item ' . $class . '>' . htmlspecialchars($selected['item'], ENT_COMPAT, 'UTF-8') . '</span>'; } } Form/Field/Title.php000064400000002741152325653710010301 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('text'); /** * Form Field class for the FOF framework * Supports a title field with an optional slug display below it. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Title extends Text implements FieldInterface { /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { // Initialise $slug_field = isset($this->element['slug_field']) ? (string)$this->element['slug_field'] : $this->item->getFieldAlias('slug'); $slug_format = $this->element['slug_format'] ? (string)$this->element['slug_format'] : '(%s)'; $slug_class = $this->element['slug_class'] ? (string)$this->element['slug_class'] : 'small'; $slug_separator = isset($this->element['slug_separator']) ? (string)$this->element['slug_separator'] : '<br />'; // Get the regular display $html = parent::getRepeatable(); $slug = $this->item->$slug_field; $html .= $slug_separator . '<span class="' . $slug_class . '">'; $html .= JText::sprintf($slug_format, $slug); $html .= '</span>'; return $html; } } Form/Field/Url.php000064400000011577152325653710007771 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('url'); /** * Form Field class for the FOF framework * Supports a URL text field. * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Url extends \JFormFieldUrl implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'id' => $this->id ); return $this->getFieldContents($options); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $options = array( 'class' => $this->id ); return $this->getFieldContents($options); } /** * Method to get the field input markup. * * @param array $fieldOptions Options to be passed into the field * * @return string The field HTML */ public function getFieldContents(array $fieldOptions = array()) { $id = isset($fieldOptions['id']) ? 'id="' . $fieldOptions['id'] . '" ' : ''; $class = $this->class . (isset($fieldOptions['class']) ? ' ' . $fieldOptions['class'] : ''); $show_link = $this->element['show_link'] == 'true'; $empty_replacement = $this->element['empty_replacement'] ? (string) $this->element['empty_replacement'] : ''; if (!empty($empty_replacement) && empty($this->value)) { $this->value = JText::_($empty_replacement); } $value = htmlspecialchars($this->value, ENT_COMPAT, 'UTF-8'); $html = $value; if ($show_link) { if ($this->element['url']) { $link_url = $this->parseFieldTags((string) $this->element['url']); } else { $link_url = $value; } $html = '<a href="' . $link_url . '">' . $value . '</a>'; } return '<span ' . ($id ? $id : '') . 'class="' . $class . '"">' . $html . '</span>'; } /** * Replace string with tags that reference fields * * @param string $text Text to process * * @return string Text with tags replace */ protected function parseFieldTags($text) { $ret = $text; // Replace [ITEM:ID] in the URL with the item's key value (usually: // the auto-incrementing numeric ID) if (is_null($this->item)) { $this->item = $this->form->getModel(); } $replace = $this->item->getId(); $ret = str_replace('[ITEM:ID]', $replace, $ret); // Replace the [ITEMID] in the URL with the current Itemid parameter $ret = str_replace('[ITEMID]', $this->form->getContainer()->input->getInt('Itemid', 0), $ret); // Replace the [TOKEN] in the URL with the Joomla! form token $ret = str_replace('[TOKEN]', \JFactory::getSession()->getFormToken(), $ret); // Replace other field variables in the URL $data = $this->item->getData(); foreach ($data as $field => $value) { // Skip non-processable values if(is_array($value) || is_object($value)) { continue; } $search = '[ITEM:' . strtoupper($field) . ']'; $ret = str_replace($search, $value, $ret); } return $ret; } } Form/Field/User.php000064400000020330152325653710010130 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('user'); /** * Form Field class for the FOF framework * A user selection box / display field * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class User extends \JFormFieldUser implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } // Initialise $show_username = !$this->element['show_username'] == 'false'; $show_email = $this->element['show_email'] == 'true'; $show_name = $this->element['show_name'] == 'true'; $show_id = $this->element['show_id'] == 'true'; $class = $this->class ? ' class="' . $this->class . '"' : ''; // Get the user record $user = $this->form->getContainer()->platform->getUser($this->value); // Render the HTML $html = '<div id="' . $this->id . '" ' . $class . '>'; if ($show_username) { $html .= '<span class="fof-userfield-username">' . $user->username . '</span>'; } if ($show_id) { $html .= '<span class="fof-userfield-id">' . $user->id . '</span>'; } if ($show_name) { $html .= '<span class="fof-userfield-name">' . $user->name . '</span>'; } if ($show_email) { $html .= '<span class="fof-userfield-email">' . $user->email . '</span>'; } $html .= '</div>'; return $html; } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { static $userCache = array(); if (isset($this->element['legacy'])) { return $this->getInput(); } // Initialise $show_username = !$this->element['show_username'] == 'false'; $show_email = !$this->element['show_email'] == 'false'; $show_name = !$this->element['show_name'] == 'false'; $show_id = !$this->element['show_id'] == 'false'; $show_avatar = !$this->element['show_avatar'] == 'false'; $show_link = $this->element['show_link'] == 'true'; $link_url = $this->element['link_url'] ? $this->element['link_url'] : null; $avatar_method = 'gravatar'; $avatar_size = $this->element['avatar_size'] ? $this->element['avatar_size'] : 64; $class = ''; // Get the user record $key = is_numeric($this->value) ? $this->value : 'empty'; $key = ($key == 0) ? 'zero' : $key; if (!array_key_exists($key, $userCache)) { $userCache[$key] = $this->form->getContainer()->platform->getUser($this->value); } $user = $userCache[$key]; // Get the field parameters if ($this->class) { $class = ' class="' . $this->class . '"'; } if ($this->element['avatar_method']) { $avatar_method = strtolower($this->element['avatar_method']); } if (!$link_url && $this->form->getContainer()->platform->isBackend()) { $link_url = 'index.php?option=com_users&task=user.edit&id=[USER:ID]'; } elseif (!$link_url) { // If no link is defined in the front-end, we can't create a // default link. Therefore, show no link. $show_link = false; } // Post-process the link URL if ($show_link) { $replacements = array( '[USER:ID]' => $user->id, '[USER:USERNAME]' => $user->username, '[USER:EMAIL]' => $user->email, '[USER:NAME]' => $user->name, ); foreach ($replacements as $key => $value) { $link_url = str_replace($key, $value, $link_url); } $link_url = $this->parseFieldTags($link_url); } // Get the avatar image, if necessary $avatar_url = ''; if ($show_avatar) { if ($avatar_method == 'plugin') { // Use the user plugins to get an avatar $this->form->getContainer()->platform->importPlugin('user'); $jResponse = $this->form->getContainer()->platform->runPlugins('onUserAvatar', array($user, $avatar_size)); if (!empty($jResponse)) { foreach ($jResponse as $response) { if ($response) { $avatar_url = $response; } } } if (empty($avatar_url)) { $show_avatar = false; } } else { // Fall back to the Gravatar method $md5 = md5($user->email); if ($this->form->getContainer()->platform->isCli()) { $scheme = 'http'; } else { $scheme = \JUri::getInstance()->getScheme(); } if ($scheme == 'http') { $avatar_url = 'http://www.gravatar.com/avatar/' . $md5 . '.jpg?s=' . $avatar_size . '&d=mm'; } else { $avatar_url = 'https://secure.gravatar.com/avatar/' . $md5 . '.jpg?s=' . $avatar_size . '&d=mm'; } } } // Generate the HTML $html = '<div id="' . $this->id . '" ' . $class . '>'; if ($show_avatar) { $html .= '<img src="' . $avatar_url . '" align="left" class="fof-usersfield-avatar" />'; } if ($show_link) { $html .= '<a href="' . $link_url . '">'; } if ($show_username) { $html .= '<span class="fof-usersfield-username">' . $user->username . '</span>'; } if ($show_id) { $html .= '<span class="fof-usersfield-id">' . $user->id . '</span>'; } if ($show_name) { $html .= '<span class="fof-usersfield-name">' . $user->name . '</span>'; } if ($show_email) { $html .= '<span class="fof-usersfield-email">' . $user->email . '</span>'; } if ($show_link) { $html .= '</a>'; } $html .= '</div>'; return $html; } /** * Replace string with tags that reference fields * * @param string $text Text to process * * @return string Text with tags replace */ protected function parseFieldTags($text) { $ret = $text; // Replace [ITEM:ID] in the URL with the item's key value (usually: // the auto-incrementing numeric ID) if (is_null($this->item)) { $this->item = $this->form->getModel(); } $replace = $this->item->getId(); $ret = str_replace('[ITEM:ID]', $replace, $ret); // Replace the [ITEMID] in the URL with the current Itemid parameter $ret = str_replace('[ITEMID]', $this->form->getContainer()->input->getInt('Itemid', 0), $ret); // Replace the [TOKEN] in the URL with the Joomla! form token $ret = str_replace('[TOKEN]', \JFactory::getSession()->getFormToken(), $ret); // Replace other field variables in the URL $data = $this->item->getData(); foreach ($data as $field => $value) { // Skip non-processable values if(is_array($value) || is_object($value)) { continue; } $search = '[ITEM:' . strtoupper($field) . ']'; $ret = str_replace($search, $value, $ret); } return $ret; } } Form/Field/UserGroup.php000064400000010732152325653710011152 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use JHtml; use JText; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('usergroup'); /** * Form Field class for FOF * Joomla! user groups * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class UserGroup extends \JFormFieldUsergroup implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { if (isset($this->element['legacy'])) { return $this->getInput(); } $class = $this->class ? ' class="' . $this->class . '"' : ''; $params = $this->getOptions(); $db = $this->form->getContainer()->platform->getDbo(); $query = $db->getQuery(true) ->select('a.id AS value, a.title AS text') ->from('#__usergroups AS a') ->group('a.id, a.title') ->order('a.id ASC') ->order($db->qn('title') . ' ASC'); // Get the options. $options = $db->setQuery($query)->loadObjectList(); // If params is an array, push these options to the array if (is_array($params)) { $options = array_merge($params, $options); } // If all levels is allowed, push it into the array. elseif ($params) { array_unshift($options, JHtml::_('select.option', '', JText::_('JOPTION_ACCESS_SHOW_ALL_LEVELS'))); } return '<span id="' . $this->id . '" ' . $class . '>' . htmlspecialchars(GenericList::getOptionName($options, $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { if (isset($this->element['legacy'])) { return $this->getInput(); } $class = $this->class ? $this->class : ''; $db = $this->form->getContainer()->platform->getDbo(); $query = $db->getQuery(true) ->select('a.id AS value, a.title AS text') ->from('#__usergroups AS a') ->group('a.id, a.title') ->order('a.id ASC') ->order($db->qn('title') . ' ASC'); // Get the options. $options = $db->setQuery($query)->loadObjectList(); return '<span class="' . $this->id . ' ' . $class . '">' . htmlspecialchars(GenericList::getOptionName($options, $this->value), ENT_COMPAT, 'UTF-8') . '</span>'; } /** * Returns the options for this control * * Adapted from JHtmlAccess::usergroup * * @return \stdClass[] */ protected function getOptions() { $db = $this->form->getContainer()->platform->getDbo(); $query = $db->getQuery(true) ->select('a.id AS value, a.title AS text, COUNT(DISTINCT b.id) AS level') ->from($db->quoteName('#__usergroups') . ' AS a') ->join('LEFT', $db->quoteName('#__usergroups') . ' AS b ON a.lft > b.lft AND a.rgt < b.rgt') ->group('a.id, a.title, a.lft, a.rgt') ->order('a.lft ASC'); $db->setQuery($query); $options = $db->loadObjectList(); for ($i = 0, $n = count($options); $i < $n; $i++) { $options[$i]->text = str_repeat('- ', $options[$i]->level) . $options[$i]->text; } } } Form/Field/ViewTemplate.php000064400000007736152325653720011640 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Field; use FOF30\Container\Container; use FOF30\Form\FieldInterface; use FOF30\Form\Form; use FOF30\Model\DataModel; use FOF30\View\View; defined('_JEXEC') or die; \JFormHelper::loadFieldClass('text'); /** * Form Field class for the FOF framework * Displays a view template loaded from an outside source * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class ViewTemplate extends \JFormField implements FieldInterface { /** * @var string Static field output */ protected $static; /** * @var string Repeatable field output */ protected $repeatable; /** * The Form object of the form attached to the form field. * * @var Form */ protected $form; /** * A monotonically increasing number, denoting the row number in a repeatable view * * @var int */ public $rowid; /** * The item being rendered in a repeatable form field * * @var DataModel */ public $item; /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'input': if (empty($this->input)) { $this->input = $this->getInput(); } return $this->input; break; case 'static': if (empty($this->static)) { $this->static = $this->getStatic(); } return $this->static; break; case 'repeatable': if (empty($this->repeatable)) { $this->repeatable = $this->getRepeatable(); } return $this->repeatable; break; default: return parent::__get($name); } } /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @since 2.0 * * @return string The field HTML */ public function getStatic() { return $this->getRenderedTemplate(); } /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @since 2.0 * * @return string The field HTML */ public function getRepeatable() { return $this->getRenderedTemplate(true); } /** * Method to get the field input markup. * * @return string The field input markup. * * @since 11.1 */ protected function getInput() { return $this->getRenderedTemplate(); } /** * Returns the rendered view template * * @return string */ protected function getRenderedTemplate($isRepeatable = false) { $sourceTemplate = isset($this->element['source']) ? (string) $this->element['source'] : null; $sourceView = isset($this->element['source_view']) ? (string) $this->element['source_view'] : null; $sourceViewType = isset($this->element['source_view_type']) ? (string) $this->element['source_view_type'] : 'html'; $sourceComponent = isset($this->element['source_component']) ? (string) $this->element['source_component'] : null; if (empty($sourceTemplate)) { return ''; } $sourceContainer = empty($sourceComponent) ? $this->form->getContainer() : Container::getInstance($sourceComponent); if (empty($sourceView)) { $viewObject = new View($sourceContainer, array( 'name' => 'FAKE_FORM_VIEW' )); } else { $viewObject = $sourceContainer->factory->view($sourceView, $sourceViewType); } $viewObject->populateFromModel($this->form->getModel()); return $viewObject->loadAnyTemplate($sourceTemplate, array( 'model' => $isRepeatable ? $this->item : $this->form->getModel(), 'rowid' => $isRepeatable ? $this->rowid : null, 'form' => $this->form, 'formType' => $this->form->getAttribute('type', 'edit'), 'fieldValue' => $this->value, 'fieldElement' => $this->element, )); } } Form/Header/AccessLevel.php000064400000001652152325653720011557 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; defined('_JEXEC') or die; /** * Access level field header * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class AccessLevel extends Selectable { /** * Method to get the list of access levels * * @return array A list of access levels. * * @since 2.0 */ protected function getOptions() { $db = $this->form->getContainer()->platform->getDbo(); $query = $db->getQuery(true); $query->select('a.id AS value, a.title AS text'); $query->from('#__viewlevels AS a'); $query->group('a.id, a.title, a.ordering'); $query->order('a.ordering ASC'); $query->order($query->qn('title') . ' ASC'); // Get the options. $db->setQuery($query); $options = $db->loadObjectList(); return $options; } } Form/Header/Date.php000064400000006171152325653720010244 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use JHtml; use JText; defined('_JEXEC') or die; /** * Generic field header, with text input (search) filter * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Date extends Field { /** * Get the filter field * * @return string The HTML */ protected function getFilter() { // Initialize some field attributes. $format = $this->element['format'] ? (string) $this->element['format'] : '%Y-%m-%d'; $attributes = array(); if ($this->element['size']) { $attributes['size'] = (int) $this->element['size']; } if ($this->element['maxlength']) { $attributes['maxlength'] = (int) $this->element['maxlength']; } if ($this->element['filterclass']) { $attributes['class'] = (string) $this->element['filterclass']; } if ((string) $this->element['readonly'] == 'true') { $attributes['readonly'] = 'readonly'; } if ((string) $this->element['disabled'] == 'true') { $attributes['disabled'] = 'disabled'; } if ($this->element['onchange']) { $attributes['onChange'] = (string) $this->element['onchange']; } else { $attributes['onChange'] = 'document.adminForm.submit()'; } if ((string) $this->element['placeholder']) { $attributes['placeholder'] = JText::_((string) $this->element['placeholder']); } $name = $this->element['searchfieldname'] ? $this->element['searchfieldname'] : $this->name; if ($this->element['searchfieldname']) { $model = $this->form->getModel(); $searchvalue = $model->getState((string) $this->element['searchfieldname']); } else { $searchvalue = $this->value; } // Get some system objects. $config = $this->form->getContainer()->platform->getConfig(); $user = $this->form->getContainer()->platform->getUser(); // If a known filter is given use it. switch (strtoupper((string) $this->element['filter'])) { case 'SERVER_UTC': // Convert a date to UTC based on the server timezone. if ((int) $this->value) { // Get a date object based on the correct timezone. $date = $this->form->getContainer()->platform->getDate($searchvalue, 'UTC'); $date->setTimezone(new \DateTimeZone($config->get('offset'))); // Transform the date string. $searchvalue = $date->format('Y-m-d H:i:s', true, false); } break; case 'USER_UTC': // Convert a date to UTC based on the user timezone. if ((int) $searchvalue) { // Get a date object based on the correct timezone. $date = $this->form->getContainer()->platform->getDate($this->value, 'UTC'); $date->setTimezone(new \DateTimeZone($user->getParam('timezone', $config->get('offset')))); // Transform the date string. $searchvalue = $date->format('Y-m-d H:i:s', true, false); } break; } return JHtml::_('calendar', $searchvalue, $name, $name, $format, $attributes); } /** * Get the buttons HTML code * * @return string The HTML */ protected function getButtons() { return ''; } } Form/Header/Field.php000064400000001516152325653720010410 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use JHtml; use JText; defined('_JEXEC') or die; /** * Generic field header, without any filters * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Field extends HeaderBase { /** * Get the header * * @return string The header HTML */ protected function getHeader() { $sortable = ($this->element['sortable'] != 'false'); $label = $this->getLabel(); if ($sortable) { $view = $this->form->getView(); return JHTML::_('grid.sort', $label, $this->name, $view->getLists()->order_Dir, $view->getLists()->order, $this->form->getModel()->task ); } else { return JText::_($label); } } } Form/Header/Filterable.php000064400000005207152325653720011437 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use JText; defined('_JEXEC') or die; /** * Generic field header, with text input (search) filter * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Filterable extends Searchable { /** * Get the filter field * * @return string The HTML */ protected function getFilter() { $valide = array('yes', 'true', '1'); // Initialize some field(s) attributes. $size = $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : ''; $maxLength = $this->element['maxlength'] ? ' maxlength="' . (int) $this->element['maxlength'] . '"' : ''; $filterclass = $this->element['filterclass'] ? ' class="' . (string) $this->element['filterclass'] . '"' : ''; $placeholder = $this->element['placeholder'] ? $this->element['placeholder'] : $this->getLabel(); $name = $this->element['searchfieldname'] ? $this->element['searchfieldname'] : $this->name; $placeholder = ' placeholder="' . JText::_($placeholder) . '"'; $single = in_array($this->element['single'], $valide) ? true : false; $showMethod = in_array($this->element['showmethod'], $valide) ? true : false; $method = $this->element['method'] ? $this->element['method'] : 'between'; $fromName = $this->element['fromname'] ? $this->element['fromname'] : 'from'; $toName = $this->element['toname'] ? $this->element['toname'] : 'to'; $values = $this->form->getModel()->getState($name); $fromValue = $values[$fromName]; $toValue = $values[$toName]; // Initialize JavaScript field attributes. if ($this->element['onchange']) { $onchange = ' onchange="' . (string) $this->element['onchange'] . '"'; } else { $onchange = ' onchange="document.adminForm.submit();"'; } if ($showMethod) { $html = '<input type="text" name="' . $name . '[method]" value="'. $method . '" />'; } else { $html = '<input type="hidden" name="' . $name . '[method]" value="'. $method . '" />'; } $html .= '<input type="text" name="' . $name . '[from]" id="' . $this->id . '_' . $fromName . '"' . ' value="' . htmlspecialchars($fromValue, ENT_COMPAT, 'UTF-8') . '"' . $filterclass . $size . $placeholder . $onchange . $maxLength . '/>'; if (!$single) { $html .= '<input type="text" name="' . $name . '[to]" id="' . $this->id . '_' . $toName . '"' . ' value="' . htmlspecialchars($toValue, ENT_COMPAT, 'UTF-8') . '"' . $filterclass . $size . $placeholder . $onchange . $maxLength . '/>'; } return $html; } } Form/Header/HeaderBase.php000064400000030360152325653720011347 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use FOF30\Form\Form; use FOF30\Form\HeaderInterface; use SimpleXMLElement; defined('_JEXEC') or die; /** * A base class for HeaderInterface fields, used to define the filters and the * elements of the header row in repeatable (browse) views * * @package FrameworkOnFramework * @since 2.0 * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ abstract class HeaderBase { /** * The description text for the form field. Usually used in tooltips. * * @var string * @since 2.0 */ protected $description; /** * The SimpleXMLElement object of the <field /> XML element that describes the header field. * * @var SimpleXMLElement * @since 2.0 */ protected $element; /** * The Form object of the form attached to the header field. * * @var Form * @since 2.0 */ protected $form; /** * The label for the header field. * * @var string * @since 2.0 */ protected $label; /** * The header HTML. * * @var string|null * @since 2.0 */ protected $header; /** * The filter HTML. * * @var string|null * @since 2.0 */ protected $filter; /** * The buttons HTML. * * @var string|null * @since 2.0 */ protected $buttons; /** * The options for a drop-down filter. * * @var array|null * @since 2.0 */ protected $options; /** * The name of the form field. * * @var string * @since 2.0 */ protected $name; /** * The name of the field. * * @var string * @since 2.0 */ protected $fieldname; /** * The group of the field. * * @var string * @since 2.0 */ protected $group; /** * The form field type. * * @var string * @since 2.0 */ protected $type; /** * The value of the filter. * * @var mixed * @since 2.0 */ protected $value; /** * The intended table data width (in pixels or percent). * * @var mixed * @since 2.0 */ protected $tdwidth; /** * The key of the filter value in the model state. * * @var mixed * @since 2.0 */ protected $filterSource; /** * The name of the filter field * * @var mixed * @since 3.0 */ protected $filterFieldName; /** * Is this a sortable column? * * @var bool * @since 2.0 */ protected $sortable = false; /** * Should we ignore the header (have the field act as just a filter)? * * @var bool * @since 3.0 */ protected $onlyFilter = false; /** * Method to instantiate the form field object. * * @param Form $form The form to attach to the form field object. * * @since 2.0 */ public function __construct(Form $form = null) { // If there is a form passed into the constructor set the form and form control properties. if ($form instanceof Form) { $this->form = $form; } } /** * Method to get certain otherwise inaccessible properties from the form field object. * * @param string $name The property name for which to the the value. * * @return mixed The property value or null. * * @since 2.0 */ public function __get($name) { switch ($name) { case 'description': case 'name': case 'type': case 'fieldname': case 'group': case 'tdwidth': case 'filterSource': case 'filterFieldName': return $this->$name; break; case 'label': if (empty($this->label)) { $this->label = $this->getLabel(); } return $this->label; case 'value': if (empty($this->value)) { $this->value = $this->getValue(); } return $this->value; break; case 'header': if (empty($this->header)) { $this->header = $this->onlyFilter ? '' : $this->getHeader(); } return $this->header; break; case 'filter': if (empty($this->filter)) { $this->filter = $this->getFilter(); } return $this->filter; break; case 'buttons': if (empty($this->buttons)) { $this->buttons = $this->getButtons(); } return $this->buttons; break; case 'options': if (empty($this->options)) { $this->options = $this->getOptions(); } return $this->options; break; case 'sortable': if (empty($this->sortable)) { $this->sortable = $this->getSortable(); } return $this->sortable; break; } return null; } /** * Method to attach a JForm object to the field. * * @param Form $form The JForm object to attach to the form field. * * @return HeaderInterface The form field object so that the method can be used in a chain. * * @since 2.0 */ public function setForm(Form $form) { $this->form = $form; return $this; } /** * Method to attach a Form object to the field. * * @param SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object. * @param string $group The field name group control value. This acts as as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * * @return boolean True on success. * * @since 2.0 */ public function setup(SimpleXMLElement $element, $group = null) { // Make sure there is a valid JFormField XML element. if ((string) $element->getName() != 'header') { return false; } // Reset the internal fields $this->label = null; $this->header = null; $this->filter = null; $this->buttons = null; $this->options = null; $this->value = null; $this->filterSource = null; $this->filterFieldName = null; // Set the XML element object. $this->element = $element; // Get some important attributes from the form field element. $id = (string) $element['id']; $name = (string) $element['name']; $filterSource = (string) $element['filter_source']; $filterFieldName = (string) $element['searchfieldname']; $tdwidth = (string) $element['tdwidth']; // Set the field description text. $this->description = (string) $element['description']; // Set the group of the field. $this->group = $group; // Set the td width of the field. $this->tdwidth = $tdwidth; // Set the field name and id. $this->fieldname = $this->getFieldName($name); $this->name = $this->getName($this->fieldname); $this->id = $this->getId($id, $this->fieldname); $this->filterSource = $this->getFilterSource($filterSource); $this->filterFieldName = $this->getFilterFieldName($filterFieldName); // Set the field default value. $this->value = $this->getValue(); // Setup the onlyFilter property $onlyFilter = $this->element['onlyFilter'] ? (string) $this->element['onlyFilter'] : false; $this->onlyFilter = in_array($onlyFilter, array('yes', 'on', '1', 'true')); return true; } /** * Method to get the id used for the field input tag. * * @param string $fieldId The field element id. * @param string $fieldName The field element name. * * @return string The id to be used for the field input tag. * * @since 2.0 */ protected function getId($fieldId, $fieldName) { $id = ''; // If the field is in a group add the group control to the field id. if ($this->group) { // If we already have an id segment add the group control as another level. if ($id) { $id .= '_' . str_replace('.', '_', $this->group); } else { $id .= str_replace('.', '_', $this->group); } } // If we already have an id segment add the field id/name as another level. if ($id) { $id .= '_' . ($fieldId ? $fieldId : $fieldName); } else { $id .= ($fieldId ? $fieldId : $fieldName); } // Clean up any invalid characters. $id = preg_replace('#\W#', '_', $id); return $id; } /** * Method to get the name used for the field input tag. * * @param string $fieldName The field element name. * * @return string The name to be used for the field input tag. * * @since 2.0 */ protected function getName($fieldName) { $name = ''; // If the field is in a group add the group control to the field name. if ($this->group) { // If we already have a name segment add the group control as another level. $groups = explode('.', $this->group); if ($name) { foreach ($groups as $group) { $name .= '[' . $group . ']'; } } else { $name .= array_shift($groups); foreach ($groups as $group) { $name .= '[' . $group . ']'; } } } // If we already have a name segment add the field name as another level. if ($name) { $name .= '[' . $fieldName . ']'; } else { $name .= $fieldName; } return $name; } /** * Method to get the field name used. * * @param string $fieldName The field element name. * * @return string The field name * * @since 2.0 */ protected function getFieldName($fieldName) { return $fieldName; } /** * Method to get the field label. * * @return string The field label. * * @since 2.0 */ protected function getLabel() { // Get the label text from the XML element, defaulting to the element name. $title = $this->element['label'] ? (string) $this->element['label'] : ''; if (empty($title)) { $viewObject = $this->form->getView(); $viewName = $viewObject->getName(); $componentName = $viewObject->getContainer()->componentName; $title = $componentName . '_' . $this->form->getModel()->getContainer()->inflector->pluralize($viewName) . '_FIELD_' . (string) $this->element['name']; $title = strtoupper($title); $result = \JText::_($title); if ($result === $title) { $title = ucfirst((string) $this->element['name']); } } return $title; } /** * Get the filter value for this header field * * @return mixed The filter value */ protected function getValue() { $model = $this->form->getModel(); return $model->getState($this->filterSource); } /** * Return the key of the filter value in the model state or, if it's not set, * the name of the field. * * @param string $filterSource The filter source value to return * * @return string */ protected function getFilterSource($filterSource) { if ($filterSource) { return $filterSource; } else { return $this->name; } } /** * Return the name of the filter field * * @param string $filterFieldName The filter field name source value to return * * @return string */ protected function getFilterFieldName($filterFieldName) { if ($filterFieldName) { return $filterFieldName; } else { return $this->filterSource; } } /** * Is this a sortable field? * * @return boolean True if it's sortable */ protected function getSortable() { $sortable = ($this->element['sortable'] != 'false'); if ($sortable) { if (empty($this->header)) { $this->header = $this->onlyFilter ? '' : $this->getHeader(); } $sortable = !empty($this->header); } return $sortable; } /** * Returns the HTML for the header row, or null if this element should * render no header element * * @return string|null HTML code or null if nothing is to be rendered * * @since 2.0 */ protected function getHeader() { return null; } /** * Returns the HTML for a text filter to be rendered in the filter row, * or null if this element should render no text input filter. * * @return string|null HTML code or null if nothing is to be rendered * * @since 2.0 */ protected function getFilter() { return null; } /** * Returns the HTML for the buttons to be rendered in the filter row, * next to the text input filter, or null if this element should render no * text input filter buttons. * * @return string|null HTML code or null if nothing is to be rendered * * @since 2.0 */ protected function getButtons() { return null; } /** * Returns the JHtml options for a drop-down filter. Do not include an * empty option, it is added automatically. * * @return array The JHtml options for a drop-down filter * * @since 2.0 */ protected function getOptions() { return array(); } } Form/Header/Language.php000064400000001633152325653720011110 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; defined('_JEXEC') or die; /** * Language field header * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Language extends Selectable { /** * Method to get the filter options. * * @return array The filter option objects. * * @since 2.0 */ protected function getOptions() { // Initialize some field attributes. $client = (string) $this->element['client']; if ($client != 'site' && $client != 'administrator') { $client = 'site'; } // Merge any additional options in the XML definition. $options = array_merge( parent::getOptions(), \JLanguageHelper::createLanguageList($this->value, constant('JPATH_' . strtoupper($client)), true, true) ); return $options; } } Form/Header/Model.php000064400000006550152325653720010430 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use FOF30\Container\Container; use FOF30\Model\DataModel; use JHtml; use JText; defined('_JEXEC') or die; if (!class_exists('JFormFieldSql')) { require_once JPATH_LIBRARIES . '/joomla/form/fields/sql.php'; } /** * Form Field class for FOF * Generic list from a model's results * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Model extends Selectable { /** * Method to get the field options. * * @return array The field option objects. */ protected function getOptions() { $options = array(); // Initialize some field attributes. $key = $this->element['key_field'] ? (string) $this->element['key_field'] : 'value'; $value = $this->element['value_field'] ? (string) $this->element['value_field'] : (string) $this->element['name']; $applyAccess = $this->element['apply_access'] ? (string) $this->element['apply_access'] : 'false'; $modelName = (string) $this->element['model']; $nonePlaceholder = (string) $this->element['none']; $translate = empty($this->element['translate']) ? 'true' : (string) $this->element['translate']; $translate = in_array(strtolower($translate), array('true','yes','1','on')) ? true : false; $with = $this->element['with'] ? (string) $this->element['with'] : null; if (!is_null($with)) { $with = trim($with); $with = explode(',', $with); $with = array_map('trim', $with); } if (!empty($nonePlaceholder)) { $options[] = JHtml::_('select.option', null, JText::_($nonePlaceholder)); } // Process field atrtibutes $applyAccess = strtolower($applyAccess); $applyAccess = in_array($applyAccess, array('yes', 'on', 'true', '1')); // Explode model name into component name and prefix $componentName = $this->form->getContainer()->componentName; $mName = $modelName; if (strpos($modelName, '.') !== false) { list ($componentName, $mName) = explode('.', $mName, 2); } // Get the applicable container $container = $this->form->getContainer(); if ($componentName != $container->componentName) { $container = Container::getInstance($componentName); } /** @var DataModel $model */ $model = $container->factory->model($mName)->setIgnoreRequest(true)->savestate(false); if ($applyAccess) { $model->applyAccessFiltering(); } if (!is_null($with)) { $model->with($with); } // Process state variables /** @var \SimpleXMLElement $stateoption */ foreach ($this->element->children() as $stateoption) { // Only add <option /> elements. if ($stateoption->getName() != 'state') { continue; } $stateKey = (string) $stateoption['key']; $stateValue = (string) $stateoption; $model->setState($stateKey, $stateValue); } // Set the query and get the result list. $items = $model->get(true); // Build the field options. if (!empty($items)) { foreach ($items as $item) { if ($translate == true) { $options[] = JHtml::_('select.option', $item->$key, JText::_($item->$value)); } else { $options[] = JHtml::_('select.option', $item->$key, $item->$value); } } } // Merge any additional options in the XML definition. $options = array_merge(parent::getOptions(), $options); return $options; } } Form/Header/Ordering.php000064400000005137152325653720011141 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use JHtml; use JText; defined('_JEXEC') or die; /** * Ordering field header * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Ordering extends Field { /** * Get the header * * @return string The header HTML */ protected function getHeader() { $sortable = ($this->element['sortable'] != 'false'); $dnd = isset($this->element['dragndrop']) ? (string) $this->element['dragndrop'] : 'notbroken'; if (strtolower($dnd) == 'notbroken') { $dnd = !version_compare(JVERSION, '3.5.0', 'ge'); } else { $dnd = in_array(strtolower($dnd), array('1', 'true', 'yes', 'on', 'enabled'), true); } if (!$sortable) { // Non sortable?! I'm not sure why you'd want that, but if you insist... return JText::_('JGRID_HEADING_ORDERING'); } $iconClass = isset($this->element['iconClass']) ? (string) $this->element['iconClass'] : 'icon-menu-2'; $class = isset($this->element['class']) ? (string) $this->element['class'] : 'btn btn-micro pull-right'; $view = $this->form->getView(); $model = $this->form->getModel(); // Drag'n'drop ordering support WITH a save order button $html = JHtml::_( 'grid.sort', '<i class="' . $iconClass . '"></i>', 'ordering', $view->getLists()->order_Dir, $view->getLists()->order, null, 'asc', 'JGRID_HEADING_ORDERING' ); $ordering = $view->getLists()->order == 'ordering'; /** * Joomla! 3.5 and later: drag and drop reordering is broken when the ordering field is not hidden * because some random bloke submitted that code and some supposedly responsible adult with commit * rights committed it. I tried to file a PR to fix it and got the reply "can't test, won't test". * OK, then. You blindly accepted code which did the EXACT OPPOSITE of what it promised and broke * b/c. However, you won't accept the fix to your mess from someone who knows how Joomla! works and * wasted 2 hours of his time to track down your mistake, fix it and explain why your actions * resulted in a b/c break. You have to be kidding me! */ $joomla35IsBroken = version_compare(JVERSION, '3.5.0', 'ge'); if ($ordering && (!$joomla35IsBroken || !$dnd)) { $html .= '<a href="javascript:saveorder(' . (count($model->get()) - 1) . ', \'saveorder\')" ' . 'rel="tooltip" class="save-order ' . $class . '" title="' . JText::_('JLIB_HTML_SAVE_ORDER') . '">' . '<span class="icon-ok"></span></a>'; } return $html; } } Form/Header/Published.php000064400000002234152325653720011302 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use JHtml; defined('_JEXEC') or die; /** * Field header for Published (enabled) columns * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Published extends Selectable { /** * Create objects for the options * * @return array The array of option objects */ protected function getOptions() { $config = array( 'published' => 1, 'unpublished' => 1, 'archived' => 0, 'trash' => 0, 'all' => 0, ); if ($this->element['show_published'] == 'false') { $config['published'] = 0; } if ($this->element['show_unpublished'] == 'false') { $config['unpublished'] = 0; } if ($this->element['show_archived'] == 'true') { $config['archived'] = 1; } if ($this->element['show_trash'] == 'true') { $config['trash'] = 1; } if ($this->element['show_all'] == 'true') { $config['all'] = 1; } $options = JHtml::_('jgrid.publishedOptions', $config); reset($options); return $options; } } Form/Header/RowSelect.php000064400000001161152325653720011270 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use JText; defined('_JEXEC') or die; /** * Row selection checkbox * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class RowSelect extends Field { /** * Get the header * * @return string The header HTML */ protected function getHeader() { return '<input type="checkbox" name="checkall-toggle" value="" title="' . JText::_('JGLOBAL_CHECK_ALL') . '" onclick="Joomla.checkAll(this)" />'; } } Form/Header/Searchable.php000064400000005212152325653720011413 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use JText; defined('_JEXEC') or die; /** * Generic field header, with text input (search) filter * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Searchable extends Field { /** * Get the filter field * * @return string The HTML */ protected function getFilter() { // Initialize some field attributes. $size = $this->element['size'] ? ' size="' . (int) $this->element['size'] . '"' : ''; $maxLength = $this->element['maxlength'] ? ' maxlength="' . (int) $this->element['maxlength'] . '"' : ''; $filterclass = $this->element['filterclass'] ? ' class="' . (string) $this->element['filterclass'] . '"' : ''; $placeholder = $this->element['placeholder'] ? $this->element['placeholder'] : $this->getLabel(); $name = $this->element['searchfieldname'] ? $this->element['searchfieldname'] : $this->name; $placeholder = ' placeholder="' . JText::_($placeholder) . '"'; if ($this->element['searchfieldname']) { $model = $this->form->getModel(); $searchvalue = $model->getState((string) $this->element['searchfieldname']); } else { $searchvalue = $this->value; } // Initialize JavaScript field attributes. if ($this->element['onchange']) { $onchange = ' onchange="' . (string) $this->element['onchange'] . '"'; } else { $onchange = ' onchange="document.adminForm.submit();"'; } return '<input type="text" name="' . $name . '" id="' . $this->id . '"' . ' value="' . htmlspecialchars($searchvalue, ENT_COMPAT, 'UTF-8') . '"' . $filterclass . $size . $placeholder . $onchange . $maxLength . '/>'; } /** * Get the buttons HTML code * * @return string The HTML */ protected function getButtons() { $buttonclass = $this->element['buttonclass'] ? (string) $this->element['buttonclass'] : 'btn hasTip hasTooltip'; $buttonsState = strtolower($this->element['buttons']); $show_buttons = !in_array($buttonsState, array('no', 'false', '0')); if (!$show_buttons) { return ''; } $html = ''; $html .= '<button class="' . $buttonclass . '" onclick="this.form.submit();" title="' . JText::_('JSEARCH_FILTER') . '" >' . "\n"; $html .= '<i class="icon-search"></i>'; $html .= '</button>' . "\n"; $html .= '<button class="' . $buttonclass . '" onclick="document.adminForm.' . $this->id . '.value=\'\';this.form.submit();" title="' . JText::_('JSEARCH_RESET') . '">' . "\n"; $html .= '<i class="icon-remove"></i>'; $html .= '</button>' . "\n"; return $html; } } Form/Header/SelectRow.php000064400000000621152325653720011270 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use JText; defined('_JEXEC') or die; /** * Row selection checkbox. Alias to RowSelect (common typo) * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class SelectRow extends RowSelect { } Form/Header/Selectable.php000064400000006334152325653720011433 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use JHtml; use JText; defined('_JEXEC') or die; /** * Generic field header, with drop down filters * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Selectable extends Field { /** * Create objects for the options * * @return array The array of option objects */ protected function getOptions() { $options = array(); // Get the field $options /** @var \SimpleXMLElement $option */ foreach ($this->element->children() as $option) { // Only add <option /> elements. if ($option->getName() != 'option') { continue; } // Create a new option object based on the <option /> element. $options[] = JHtml::_( 'select.option', (string) $option['value'], JText::alt( trim((string) $option), preg_replace('/[^a-zA-Z0-9_\-]/', '_', $this->fieldname) ), 'value', 'text', ((string) $option['disabled'] == 'true') ); } // Do we have a class and method source for our options? $source_file = empty($this->element['source_file']) ? '' : (string) $this->element['source_file']; $source_class = empty($this->element['source_class']) ? '' : (string) $this->element['source_class']; $source_method = empty($this->element['source_method']) ? '' : (string) $this->element['source_method']; $source_key = empty($this->element['source_key']) ? '*' : (string) $this->element['source_key']; $source_value = empty($this->element['source_value']) ? '*' : (string) $this->element['source_value']; $source_translate = empty($this->element['source_translate']) ? 'true' : (string) $this->element['source_translate']; $source_translate = in_array(strtolower($source_translate), array('true','yes','1','on')) ? true : false; $source_format = empty($this->element['source_format']) ? '' : (string) $this->element['source_format']; if ($source_class && $source_method) { // Maybe we have to load a file? if (!empty($source_file)) { $source_file = $this->form->getContainer()->template->parsePath($source_file, true); if ($this->form->getContainer()->filesystem->fileExists($source_file)) { include_once $source_file; } } // Make sure the class exists if (class_exists($source_class, true)) { // ...and so does the option if (in_array($source_method, get_class_methods($source_class))) { // Get the data from the class if ($source_format == 'optionsobject') { $options = array_merge($options, $source_class::$source_method()); } else { $source_data = $source_class::$source_method(); // Loop through the data and prime the $options array foreach ($source_data as $k => $v) { $key = (empty($source_key) || ($source_key == '*')) ? $k : @$v[$source_key]; $value = (empty($source_value) || ($source_value == '*')) ? $v : @$v[$source_value]; if ($source_translate) { $value = JText::_($value); } $options[] = JHtml::_('select.option', $key, $value, 'value', 'text'); } } } } } reset($options); return $options; } } Form/Header/Sql.php000064400000003115152325653720010121 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form\Header; use JHtml; use JText; defined('_JEXEC') or die; /** * Generic field header, with drop down filters based on a SQL query * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Sql extends Selectable { /** * Create objects for the options * * @return array The array of option objects */ protected function getOptions() { $options = array(); // Initialize some field attributes. $key = $this->element['key_field'] ? (string) $this->element['key_field'] : 'value'; $value = $this->element['value_field'] ? (string) $this->element['value_field'] : (string) $this->element['name']; $translate = $this->element['translate'] ? (string) $this->element['translate'] : false; $query = (string) $this->element['query']; // Get the database object. $db = $this->form->getContainer()->platform->getDbo(); // Set the query and get the result list. $db->setQuery($query); $items = $db->loadObjectlist(); // Build the field options. if (!empty($items)) { foreach ($items as $item) { if ($translate == true) { $options[] = JHtml::_('select.option', $item->$key, JText::_($item->$value)); } else { $options[] = JHtml::_('select.option', $item->$key, $item->$value); } } } // Merge any additional options in the XML definition. $options = array_merge(parent::getOptions(), $options); return $options; } } Form/FieldInterface.php000064400000005251152325653720011041 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form; defined('_JEXEC') or die; /** * Generic interface that a FOF form field class must implement * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ interface FieldInterface { /** * Method to attach a JForm object to the field. Actually, we need a FOF Form object but there's no way to provide * that type hint without issuing a string standards notice in PHP :( * * @param Form $form The JForm object to attach to the form field. * * @return FieldInterface The form field object so that the method can be used in a chain. */ public function setForm(\JForm $form); /** * Method to attach a Form object to the field. * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the <field /> tag for the form field object. * @param mixed $value The form field value to validate. * @param string $group The field name group control value. This acts as as an array container for the field. * For example if the field has name="foo" and the group value is set to "bar" then the * full field name would end up being "bar[foo]". * * @return boolean True on success. */ public function setup(\SimpleXMLElement $element, $value, $group = null); /** * Simple method to set the value * * @param mixed $value Value to set * * @return void */ public function setValue($value); /** * Method to get an attribute of the field * * @param string $name Name of the attribute to get * @param mixed $default Optional value to return if attribute not found * * @return mixed Value of the attribute / default */ public function getAttribute($name, $default = null); /** * Method to get a control group with label and input. * * @param array $options Options to be passed into the rendering of the field * * @return string A string containing the html for the control group */ public function renderField($options = array()); /** * Get the rendering of this field type for static display, e.g. in a single * item view (typically a "read" task). * * @return string The field HTML * * @since 2.0 */ public function getStatic(); /** * Get the rendering of this field type for a repeatable (grid) display, * e.g. in a view listing many item (typically a "browse" task) * * @return string The field HTML * * @since 2.0 */ public function getRepeatable(); } Form/Form.php000064400000071360152325653720007104 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form; use FOF30\Container\Container; use FOF30\Form\Header\HeaderBase; use FOF30\Model\DataModel; use FOF30\View\DataView\DataViewInterface; use JFactory; use JForm; use Joomla\Registry\Registry; use JText; use SimpleXMLElement; defined('_JEXEC') or die; /** * Form is an extension to JForm which support not only edit views but also * browse (record list) and read (single record display) views based on XML * forms. * * @package FrameworkOnFramework * @since 2.0 * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ class Form extends JForm { /** * The model attached to this view * * @var DataModel */ protected $model; /** * The view used to render this form * * @var DataViewInterface */ protected $view; /** * The Container this form belongs to * * @var \FOF30\Container\Container */ protected $container; /** * Map of entity objects for re-use. * Prototypes for all fields and rules are here. * * Array's structure: * <code> * entities: * {ENTITY_NAME}: * {KEY}: {OBJECT} * </code> * * @var array */ protected $entities = array(); /** * Method to instantiate the form object. * * @param Container $container The component Container where this form belongs to * @param string $name The name of the form. * @param array $options An array of form options. */ public function __construct(Container $container, $name, array $options = array()) { parent::__construct($name, $options); $this->container = $container; } /** * Returns the value of an attribute of the form itself * * @param string $attribute The name of the attribute * @param mixed $default Optional default value to return * * @return mixed * * @since 2.0 */ public function getAttribute($attribute, $default = null) { $value = $this->xml->attributes()->$attribute; if (is_null($value)) { return $default; } else { return (string)$value; } } /** * Loads the CSS files defined in the form, based on its cssfiles attribute * * @return void * * @since 2.0 */ public function loadCSSFiles() { // Support for CSS files $cssfiles = $this->getAttribute('cssfiles'); if (!empty($cssfiles)) { $cssfiles = explode(',', $cssfiles); foreach ($cssfiles as $cssfile) { $this->getView()->addCssFile(trim($cssfile)); } } // Support for LESS files $lessfiles = $this->getAttribute('lessfiles'); if (!empty($lessfiles)) { $lessfiles = explode(',', $lessfiles); foreach ($lessfiles as $def) { $parts = explode('||', $def, 2); $lessfile = $parts[0]; $alt = (count($parts) > 1) ? trim($parts[1]) : null; $this->getView()->addLess(trim($lessfile), $alt); } } } /** * Loads the Javascript files defined in the form, based on its jsfiles attribute * * @return void * * @since 2.0 */ public function loadJSFiles() { $jsfiles = $this->getAttribute('jsfiles'); if (empty($jsfiles)) { return; } $jsfiles = explode(',', $jsfiles); foreach ($jsfiles as $jsfile) { $this->getView()->addJavascriptFile(trim($jsfile)); } } /** * Returns a reference to the protected $data object, allowing direct * access to and manipulation of the form's data. * * @return \JRegistry|Registry The form's data registry * * @since 2.0 */ public function &getData() { return $this->data; } /** * Method to load the form description from an XML file. * * The reset option works on a group basis. If the XML file references * groups that have already been created they will be replaced with the * fields in the new XML file unless the $reset parameter has been set * to false. * * @param string $file The filesystem path of an XML file. * @param bool $reset Flag to toggle whether form fields should be replaced if a field * already exists with the same group/name. * @param bool $xpath An optional xpath to search for the fields. * * @return boolean True on success, false otherwise. */ public function loadFile($file, $reset = true, $xpath = false) { // Check to see if the path is an absolute path. if (!is_file($file)) { return false; } // Attempt to load the XML file. $xml = simplexml_load_file($file); return $this->load($xml, $reset, $xpath); } /** * Attaches a DataModel to this form * * @param DataModel &$model The model to attach to the form * * @return void */ public function setModel(DataModel &$model) { $this->model = $model; } /** * Returns the DataModel attached to this form * * @return DataModel */ public function &getModel() { return $this->model; } /** * Attaches a DataViewInterface to this form * * @param DataViewInterface &$view The view to attach to the form * * @return void */ public function setView(DataViewInterface &$view) { $this->view = $view; } /** * Returns the DataViewInterface attached to this form * * @return DataViewInterface */ public function &getView() { return $this->view; } /** * Method to get an array of FormHeader objects in the headerset. * * @return array The array of HeaderInterface objects in the headerset. * * @since 2.0 */ public function getHeaderset() { $fields = array(); $elements = $this->findHeadersByGroup(); // If no field elements were found return empty. if (empty($elements)) { return $fields; } // Build the result array from the found field elements. /** @var \SimpleXMLElement $element */ foreach ($elements as $element) { // Get the field groups for the element. $attrs = $element->xpath('ancestor::headerset[@name]/@name'); $groups = array_map('strval', $attrs ? $attrs : array()); $group = implode('.', $groups); // If the field is successfully loaded add it to the result array. /** @var HeaderBase $field */ if ($field = $this->loadHeader($element, $group)) { $fields[$field->id] = $field; } } return $fields; } /** * Method to get an array of <header /> elements from the form XML document which are * in a control group by name. * * @param mixed $group The optional dot-separated form group path on which to find the fields. * Null will return all fields. False will return fields not in a group. * @param boolean $nested True to also include fields in nested groups that are inside of the * group for which to find fields. * * @return \SimpleXMLElement|bool Boolean false on error or array of SimpleXMLElement objects. * * @since 2.0 */ protected function &findHeadersByGroup($group = null, $nested = false) { $false = false; $fields = array(); // Make sure there is a valid JForm XML document. if (!($this->xml instanceof \SimpleXMLElement)) { return $false; } // Get only fields in a specific group? if ($group) { // Get the fields elements for a given group. $elements = &$this->findHeader($group); // Get all of the field elements for the fields elements. /** @var \SimpleXMLElement $element */ foreach ($elements as $element) { // If there are field elements add them to the return result. if ($tmp = $element->xpath('descendant::header')) { // If we also want fields in nested groups then just merge the arrays. if ($nested) { $fields = array_merge($fields, $tmp); } // If we want to exclude nested groups then we need to check each field. else { $groupNames = explode('.', $group); foreach ($tmp as $field) { // Get the names of the groups that the field is in. $attrs = $field->xpath('ancestor::headers[@name]/@name'); $names = array_map('strval', $attrs ? $attrs : array()); // If the field is in the specific group then add it to the return list. if ($names == (array)$groupNames) { $fields = array_merge($fields, array($field)); } } } } } } elseif ($group === false) { // Get only field elements not in a group. $fields = $this->xml->xpath('descendant::headers[not(@name)]/header | descendant::headers[not(@name)]/headerset/header '); } else { // Get an array of all the <header /> elements. $fields = $this->xml->xpath('//header'); } return $fields; } /** * Method to get a header field represented as a HeaderInterface object. * * @param string $name The name of the header field. * @param string $group The optional dot-separated form group path on which to find the field. * @param mixed $value The optional value to use as the default for the field. (DEPRECATED) * * @return HeaderInterface|bool The HeaderInterface object for the field or boolean false on error. * * @since 2.0 */ public function getHeader($name, $group = null, $value = null) { // Make sure there is a valid Form XML document. if (!($this->xml instanceof \SimpleXMLElement)) { return false; } // Attempt to find the field by name and group. $element = $this->findHeader($name, $group); // If the field element was not found return false. if (!$element) { return false; } return $this->loadHeader($element, $group); } /** * Method to get a header field represented as an XML element object. * * @param string $name The name of the form field. * @param string $group The optional dot-separated form group path on which to find the field. * * @return mixed The XML element object for the field or boolean false on error. * * @since 2.0 */ protected function findHeader($name, $group = null) { $element = false; $fields = array(); // Make sure there is a valid JForm XML document. if (!($this->xml instanceof \SimpleXMLElement)) { return false; } // Let's get the appropriate field element based on the method arguments. if ($group) { // Get the fields elements for a given group. $elements = &$this->findGroup($group); // Get all of the field elements with the correct name for the fields elements. /** @var \SimpleXMLElement $element */ foreach ($elements as $element) { // If there are matching field elements add them to the fields array. if ($tmp = $element->xpath('descendant::header[@name="' . $name . '"]')) { $fields = array_merge($fields, $tmp); } } // Make sure something was found. if (!$fields) { return false; } // Use the first correct match in the given group. $groupNames = explode('.', $group); /** @var \SimpleXMLElement $field */ foreach ($fields as &$field) { // Get the group names as strings for ancestor fields elements. $attrs = $field->xpath('ancestor::headerfields[@name]/@name'); $names = array_map('strval', $attrs ? $attrs : array()); // If the field is in the exact group use it and break out of the loop. if ($names == (array)$groupNames) { $element = &$field; break; } } } else { // Get an array of fields with the correct name. $fields = $this->xml->xpath('//header[@name="' . $name . '"]'); // Make sure something was found. if (!$fields) { return false; } // Search through the fields for the right one. foreach ($fields as &$field) { // If we find an ancestor fields element with a group name then it isn't what we want. if ($field->xpath('ancestor::headerfields[@name]')) { continue; } // Found it! else { $element = &$field; break; } } } return $element; } /** * Method to load, setup and return a HeaderInterface object based on field data. * * @param string $element The XML element object representation of the form field. * @param string $group The optional dot-separated form group path on which to find the field. * * @return HeaderInterface|bool The HeaderInterface object for the field or boolean false on error. * * @since 2.0 */ protected function loadHeader($element, $group = null) { // Make sure there is a valid SimpleXMLElement. if (!($element instanceof \SimpleXMLElement)) { return false; } // Get the field type. $type = $element['type'] ? (string)$element['type'] : 'field'; // Load the JFormField object for the field. $field = $this->loadHeaderType($type); // If the object could not be loaded, get a text field object. if ($field === false) { $field = $this->loadHeaderType('field'); } // Setup the HeaderInterface object. $field->setForm($this); if ($field->setup($element, $group)) { return $field; } else { return false; } } /** * Method to remove a header from the form definition. * * @param string $name The name of the form field for which remove. * @param string $group The optional dot-separated form group path on which to find the field. * * @return boolean True on success, false otherwise. * * @throws \UnexpectedValueException */ public function removeHeader($name, $group = null) { // Make sure there is a valid JForm XML document. if (!($this->xml instanceof SimpleXMLElement)) { throw new \UnexpectedValueException(sprintf('%s::getFieldAttribute `xml` is not an instance of SimpleXMLElement', get_class($this))); } // Find the form field element from the definition. $element = $this->findHeader($name, $group); // If the element exists remove it from the form definition. if ($element instanceof SimpleXMLElement) { $dom = dom_import_simplexml($element); $dom->parentNode->removeChild($dom); return true; } return false; } /** * Proxy for {@link Helper::loadFieldType()}. * * @param string $type The field type. * @param boolean $new Flag to toggle whether we should get a new instance of the object. * * @return FieldInterface|bool FieldInterface object on success, false otherwise. * * @since 2.0 */ protected function loadFieldType($type, $new = true) { return $this->loadType('field', $type, $new); } /** * Proxy for {@link Helper::loadHeaderType()}. * * @param string $type The field type. * @param boolean $new Flag to toggle whether we should get a new instance of the object. * * @return HeaderInterface|bool HeaderInterface object on success, false otherwise. * * @since 2.0 */ protected function loadHeaderType($type, $new = true) { return $this->loadType('header', $type, $new); } /** * Proxy for {@link Helper::loadRuleType()}. * * @param string $type The rule type. * @param boolean $new Flag to toggle whether we should get a new instance of the object. * * @return \JFormRule|bool JFormRule object on success, false otherwise. * * @see Helper::loadRuleType() * @since 2.0 */ protected function loadRuleType($type, $new = true) { return $this->loadType('rule', $type, $new); } /** * Method to load a form entity object given a type. * Each type is loaded only once and then used as a prototype for other objects of same type. * Please, use this method only with those entities which support types (forms don't support them). * * @param string $entity The entity. * @param string $type The entity type. * @param boolean $new Flag to toggle whether we should get a new instance of the object. * * @return mixed Entity object on success, false otherwise. */ protected function loadType($entity, $type, $new = true) { // Reference to an array with current entity's type instances $types = &$this->entities[$entity]; // Return an entity object if it already exists and we don't need a new one. if (isset($types[$type]) && $new === false) { return $types[$type]; } $class = $this->loadClass($entity, $type); if ($class !== false) { // Instantiate a new type object. $types[$type] = new $class; return $types[$type]; } else { return false; } } /** * Load a class for one of the form's entities of a particular type. * Currently, it makes sense to use this method for the "field" and "rule" entities * (but you can support more entities in your subclass). * * @param string $entity One of the form entities (field, header or rule). * @param string $type Type of an entity. * * @return mixed Class name on success or false otherwise. * * @since 2.0 */ public function loadClass($entity, $type) { // Get the prefixes for namespaced classes (FOF3 way) $namespacedPrefixes = array( $this->container->getNamespacePrefix(), 'FOF30\\', ); // Get the prefixes for non-namespaced classes (FOF2 and Joomla! way) $plainPrefixes = array('J'); // If the type is given as prefix.type add the custom type into the two prefix arrays if (strpos($type, '.')) { list($prefix, $type) = explode('.', $type); array_unshift($plainPrefixes, $prefix); array_unshift($namespacedPrefixes, $prefix); } // First try to find the namespaced class foreach ($namespacedPrefixes as $prefix) { $class = rtrim($prefix, '\\') . '\\Form\\' . ucfirst($entity) . '\\' . ucfirst($type); if (class_exists($class, true)) { return $class; } } // TODO The rest of the code is legacy and will be removed in a future version // Then try to find the non-namespaced class $classes = array(); foreach ($plainPrefixes as $prefix) { $class = \JString::ucfirst($prefix, '_') . 'Form' . \JString::ucfirst($entity, '_') . \JString::ucfirst($type, '_'); if (class_exists($class, true)) { return $class; } $classes[] = $class; } // Get the field search path array. $reflector = new \ReflectionClass('\\JFormHelper'); $addPathMethod = $reflector->getMethod('addPath'); $addPathMethod->setAccessible(true); $paths = $addPathMethod->invoke(null, $entity); // If the type is complex, add the base type to the paths. if ($pos = strpos($type, '_')) { // Add the complex type prefix to the paths. for ($i = 0, $n = count($paths); $i < $n; $i++) { // Derive the new path. $path = $paths[$i] . '/' . strtolower(substr($type, 0, $pos)); // If the path does not exist, add it. if (!in_array($path, $paths)) { $paths[] = $path; } } // Break off the end of the complex type. $type = substr($type, $pos + 1); } // Try to find the class file. $type = strtolower($type) . '.php'; foreach ($paths as $path) { if ($file = \JPath::find($path, $type)) { require_once $file; foreach ($classes as $class) { if (class_exists($class, false)) { return $class; } } } } return false; } /** * WARNING: THIS IS IGNORED IN FOF3! * * @param string $new IGNORED! * * @return void * * @deprecated 3.0 */ public static function addFieldPath($new = null) { if ($new) {}; // Prevents phpStorm from freaking out about the unused $new parameter... if (class_exists('JLog')) { \JLog::add(__CLASS__ . '::' . __METHOD__ . '() is deprecated since FOF 3.0 and should not be used.', \JLog::WARNING, 'deprecated'); } } /** * WARNING: THIS IS IGNORED IN FOF3! * * @param string $new IGNORED! * * @return void * * @deprecated 3.0 */ public static function addHeaderPath($new = null) { if ($new) {}; // Prevents phpStorm from freaking out about the unused $new parameter... if (class_exists('JLog')) { \JLog::add(__CLASS__ . '::' . __METHOD__ . '() is deprecated since FOF 3.0 and should not be used.', \JLog::WARNING, 'deprecated'); } } /** * WARNING: THIS IS IGNORED IN FOF3! * * @param string $new IGNORED! * * @return void * * @deprecated 3.0 */ public static function addFormPath($new = null) { if ($new) {}; // Prevents phpStorm from freaking out about the unused $new parameter... if (class_exists('JLog')) { \JLog::add(__CLASS__ . '::' . __METHOD__ . '() is deprecated since FOF 3.0 and should not be used.', \JLog::WARNING, 'deprecated'); } } /** * WARNING: THIS IS IGNORED IN FOF3! * * @param string $new IGNORED! * * @return void * * @deprecated 3.0 */ public static function addRulePath($new = null) { if ($new) {}; // Prevents phpStorm from freaking out about the unused $new parameter... if (class_exists('JLog')) { \JLog::add(__CLASS__ . '::' . __METHOD__ . '() is deprecated since FOF 3.0 and should not be used.', \JLog::WARNING, 'deprecated'); } } /** * Get a reference to the form's Container * * @return Container */ public function &getContainer() { return $this->container; } /** * Set the form's Container * * @param Container $container */ public function setContainer($container) { $this->container = $container; } /** * Method to bind data to the form. * * @param mixed $data An array or object of data to bind to the form. * * @return boolean True on success. * * @since 11.1 */ public function bind($data) { $this->data = class_exists('JRegistry') ? new \JRegistry() : new Registry(); if (is_object($data) && ($data instanceof DataModel)) { $maxDepth = (int) $this->getAttribute('relation_depth', '1'); return parent::bind($this->modelToBindSource($data, $maxDepth)); } return parent::bind($data); } /** * Method to bind data to the form for the group level. * * @param string $group The dot-separated form group path on which to bind the data. * @param mixed $data An array or object of data to bind to the form for the group level. * * @return void * * @since 11.1 */ protected function bindLevel($group, $data) { if (is_object($data) && ($data instanceof DataModel)) { parent::bindLevel($group, $this->modelToBindSource($data)); return; } parent::bindLevel($group, $data); } /** * Method to load, setup and return a JFormField object based on field data. * * @param string $element The XML element object representation of the form field. * @param string $group The optional dot-separated form group path on which to find the field. * @param mixed $value The optional value to use as the default for the field. * * @return mixed The JFormField object for the field or boolean false on error. * * @since 11.1 */ protected function loadField($element, $group = null, $value = null) { // Make sure there is a valid SimpleXMLElement. if (!($element instanceof SimpleXMLElement)) { return false; } // Get the field type. $type = $element['type'] ? (string) $element['type'] : 'text'; // Load the JFormField object for the field. $field = $this->loadFieldType($type); // If the object could not be loaded, get a text field object. if ($field === false) { $field = $this->loadFieldType('text'); } /* * Get the value for the form field if not set. * Default to the translated version of the 'default' attribute * if 'translate_default' attribute if set to 'true' or '1' * else the value of the 'default' attribute for the field. */ if ($value === null) { $default = (string) $element['default']; if (($translate = $element['translate_default']) && ((string) $translate == 'true' || (string) $translate == '1')) { $lang = JFactory::getLanguage(); if ($lang->hasKey($default)) { $debug = $lang->setDebug(false); $default = JText::_($default); $lang->setDebug($debug); } else { $default = JText::_($default); } } $getValueFrom = (isset($element['name_from'])) ? (string) $element['name_from'] : (string) $element['name']; $value = $this->getValue($getValueFrom, $group, $default); } // Setup the JFormField object. $field->setForm($this); if ($field->setup($element, $value, $group)) { return $field; } else { return false; } } /** * Method to get a form field represented as an XML element object. * * @param string $name The name of the form field. * @param string $group The optional dot-separated form group path on which to find the field. * * @return mixed The XML element object for the field or boolean false on error. * * @since 11.1 */ protected function findField($name, $group = null) { $element = false; $fields = array(); // Make sure there is a valid JForm XML document. if (!($this->xml instanceof SimpleXMLElement)) { return false; } // Let's get the appropriate field element based on the method arguments. if ($group) { // Get the fields elements for a given group. $elements = &$this->findGroup($group); // Get all of the field elements with the correct name for the fields elements. /** @var SimpleXMLElement $element */ foreach ($elements as $element) { // If there are matching field elements add them to the fields array. if ($tmp = $element->xpath('descendant::field[@name="' . $name . '"]')) { $fields = array_merge($fields, $tmp); } elseif ($tmp = $element->xpath('descendant::field[@name_from="' . $name . '"]')) { $fields = array_merge($fields, $tmp); } } // Make sure something was found. if (!$fields) { return false; } // Use the first correct match in the given group. $groupNames = explode('.', $group); /** @var SimpleXMLElement $field */ foreach ($fields as &$field) { // Get the group names as strings for ancestor fields elements. $attrs = $field->xpath('ancestor::fields[@name]/@name'); $names = array_map('strval', $attrs ? $attrs : array()); // If the field is in the exact group use it and break out of the loop. if ($names == (array) $groupNames) { $element = &$field; break; } } } else { // Get an array of fields with the correct name. $fields = $this->xml->xpath('//field[@name="' . $name . '"]'); if (!$fields) { $fields = array(); } $fieldsNameFrom = $this->xml->xpath('//field[@name_from="' . $name . '"]'); if ($fieldsNameFrom) { $fields = array_merge($fields, $fieldsNameFrom); } // Make sure something was found. if (empty($fields)) { return false; } // Search through the fields for the right one. foreach ($fields as &$field) { // If we find an ancestor fields element with a group name then it isn't what we want. if ($field->xpath('ancestor::fields[@name]')) { continue; } // Found it! else { $element = &$field; break; } } } return $element; } /** * Converts a DataModel into data suitable for use with the form. The difference to the Model's getData() method is * that we process hasOne and belongsTo relations. This is a recursive function which will be called at most * $maxLevel deep. You can set this in the form XML file, in the relation_depth attribute. * * The $modelsProcessed array which is passed in successive recursions lets us prevent pointless Inception-style * recursions, e.g. Model A is related to Model B is related to Model C is related to Model A. You clearly don't * care to see a.b.c.a.b in the results. You just want a.b.c. Obviously c is indirectly related to a because that's * where you began the recursion anyway. * * @param DataModel $model The item to dump its contents into an array * @param int $maxLevel Maximum nesting level of relations to process. Default: 1. * @param array $modelsProcessed Array of the fully qualified model class names already processed. * * @return array * @throws DataModel\Relation\Exception\RelationNotFound */ protected function modelToBindSource(DataModel $model, $maxLevel = 1, $modelsProcessed = array()) { $maxLevel--; $data = $model->toArray(); $relations = $model->getRelations()->getRelationNames(); $relationTypes = $model->getRelations()->getRelationTypes(); $relationTypes = array_map(function ($x) { return ltrim($x, '\\'); }, $relationTypes); $relationTypes = array_flip($relationTypes); if (is_array($relations) && count($relations) && ($maxLevel >= 0)) { foreach ($relations as $relationName) { $rel = $model->getRelations()->getRelation($relationName); $class = get_class($rel); if (!isset($relationTypes[$class])) { continue; } if (!in_array($relationTypes[$class], array('hasOne', 'belongsTo'))) { continue; } /** @var DataModel $relData */ $relData = $model->$relationName; if (!($relData instanceof DataModel)) { continue; } $modelType = get_class($relData); if (in_array($modelType, $modelsProcessed)) { continue; } $modelsProcessed[] = $modelType; $relDataArray = $this->modelToBindSource($relData, $maxLevel, $modelsProcessed); if (!is_array($relDataArray) || empty($relDataArray)) { continue; } foreach ($relDataArray as $k => $v) { $data[$relationName . '.' . $k] = $v; } } } return $data; } } Form/HeaderInterface.php000064400000002455152325653720011211 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Form; defined('_JEXEC') or die; /** * Generic interface that a FOF header field class must implement * * @deprecated 3.1 Support for XML forms will be removed in FOF 4 */ interface HeaderInterface { /** * Method to attach a Form object to the header. * * @param Form $form The Form object to attach to the form field. * * @return HeaderInterface The form field object so that the method can be used in a chain. * * @since 2.0 */ public function setForm(Form $form); /** * Method to attach a Form object to the header. * * @param \SimpleXMLElement $element The SimpleXMLElement object representing the <header /> tag for the form header object. * @param string $group The header name group control value. This acts as as an array container for the header. * For example if the header has name="foo" and the group value is set to "bar" then the * full header name would end up being "bar[foo]". * * @return boolean True on success. */ public function setup(\SimpleXMLElement $element, $group = null); } Hal/Exception/InvalidLinkFormat.php000064400000001003152325653720013300 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Hal\Exception; use Exception; defined('_JEXEC') or die; class InvalidLinkFormat extends \RuntimeException { public function __construct($message = '', $code = 500, Exception $previous = null) { if (empty($message)) { $message = \JText::_('LIB_FOF_HAL_ERR_INVALIDLINK'); } parent::__construct($message, $code, $previous); } } Hal/Exception/InvalidRenderFormat.php000064400000000766152325653720013641 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Hal\Exception; use Exception; defined('_JEXEC') or die; class InvalidRenderFormat extends \RuntimeException { public function __construct($format, $code = 500, Exception $previous = null) { $message = \JText::sprintf('LIB_FOF_HAL_ERR_INVALIDRENDERFORMAT', $format); parent::__construct($message, $code, $previous); } } Hal/Render/Json.php000064400000006454152325653720010134 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Hal\Render; use FOF30\Hal\Document; use FOF30\Hal\Link; use FOF30\Model\DataModel; defined('_JEXEC') or die; /** * Implements the HAL over JSON renderer * * @see http://stateless.co/hal_specification.html */ class Json implements RenderInterface { /** * When data is an array we'll output the list of data under this key * * @var string */ private $_dataKey = '_list'; /** * The document to render * * @var Document */ protected $_document; /** * Public constructor * * @param Document &$document The document to render */ public function __construct(Document &$document) { $this->_document = $document; } /** * Render a HAL document in JSON format * * @param array $options Rendering options. You can currently only set json_options (json_encode options) * * @return string The JSON representation of the HAL document */ public function render($options = array()) { if (isset($options['data_key'])) { $this->_dataKey = $options['data_key']; } if (isset($options['json_options'])) { $jsonOptions = $options['json_options']; } else { $jsonOptions = 0; } $serialiseThis = new \stdClass; // Add links $collection = $this->_document->getLinks(); $serialiseThis->_links = new \stdClass; foreach ($collection as $rel => $links) { if (!is_array($links)) { $serialiseThis->_links->$rel = $this->_getLink($links); } else { $serialiseThis->_links->$rel = array(); foreach ($links as $link) { array_push($serialiseThis->_links->$rel, $this->_getLink($link)); } } } // Add embedded documents $collection = $this->_document->getEmbedded(); if (!empty($collection)) { $serialiseThis->_embedded = new \stdClass; foreach ($collection as $rel => $embeddeddocs) { $serialiseThis->_embedded->$rel = array(); if (!is_array($embeddeddocs)) { $embeddeddocs = array($embeddeddocs); } foreach ($embeddeddocs as $embedded) { $renderer = new static($embedded); array_push($serialiseThis->_embedded->$rel, $renderer->render($options)); } } } // Add data $data = $this->_document->getData(); if (is_object($data)) { if ($data instanceof DataModel) { $data = $data->toArray(); } else { $data = (array) $data; } if (!empty($data)) { foreach ($data as $k => $v) { $serialiseThis->$k = $v; } } } elseif (is_array($data)) { $serialiseThis->{$this->_dataKey} = $data; } return json_encode($serialiseThis, $jsonOptions); } /** * Converts a FOFHalLink object into a stdClass object which will be used * for JSON serialisation * * @param Link $link The link you want converted * * @return \stdClass The converted link object */ protected function _getLink(Link $link) { $ret = array( 'href' => $link->href ); if ($link->templated) { $ret['templated'] = 'true'; } if ($link->name) { $ret['name'] = $link->name; } if ($link->hreflang) { $ret['hreflang'] = $link->hreflang; } if ($link->title) { $ret['title'] = $link->title; } return (object) $ret; } } Hal/Render/RenderInterface.php000064400000001107152325653720012251 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Hal\Render; defined('_JEXEC') or die; /** * Interface for HAL document renderers * * @see http://stateless.co/hal_specification.html * * @codeCoverageIgnore */ interface RenderInterface { /** * Render a HAL document into a representation suitable for consumption. * * @param array $options Renderer-specific options * * @return string */ public function render($options = array()); } Hal/Document.php000064400000012555152325653720007561 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Hal; use FOF30\Hal\Exception\InvalidRenderFormat; use FOF30\Hal\Render\RenderInterface; defined('_JEXEC') or die; /** * Implementation of the Hypertext Application Language document in PHP. It can * be used to provide hypermedia in a web service context. * * @see http://stateless.co/hal_specification.html */ class Document { /** * The collection of links of this document * * @var \FOF30\Hal\Links */ private $_links = null; /** * The data (resource state or collection of resource state objects) of the * document. * * @var array */ private $_data = null; /** * Embedded documents. This is an array of FOFHalDocument instances. * * @var array */ private $_embedded = array(); /** * When $_data is an array we'll output the list of data under this key * (JSON) or tag (XML) * * @var string */ private $_dataKey = '_list'; /** * Public constructor * * @param mixed $data The data of the document (usually, the resource state) */ public function __construct($data = null) { $this->_data = $data; $this->_links = new Links; } /** * Add a link to the document * * @param string $rel The relation of the link to the document. * See RFC 5988 http://tools.ietf.org/html/rfc5988#section-6.2.2 A document MUST always have * a "self" link. * @param Link $link The actual link object * @param boolean $overwrite When false and a link of $rel relation exists, an array of links is created. Otherwise the * existing link is overwriten with the new one * * @see Links::addLink * * @return boolean True if the link was added to the collection */ public function addLink($rel, Link $link, $overwrite = true) { return $this->_links->addLink($rel, $link, $overwrite); } /** * Add links to the document * * @param string $rel The relation of the link to the document. See RFC 5988 * @param array $links An array of FOFHalLink objects * @param boolean $overwrite When false and a link of $rel relation exists, an array of * links is created. Otherwise the existing link is overwriten * with the new one * * @see Links::addLinks * * @return boolean */ public function addLinks($rel, array $links, $overwrite = true) { return $this->_links->addLinks($rel, $links, $overwrite); } /** * Add data to the document * * @param \stdClass $data The data to add * @param boolean $overwrite Should I overwrite existing data? * * @return void */ public function addData($data, $overwrite = true) { if (is_array($data)) { $data = (object) $data; } if ($overwrite) { $this->_data = $data; } else { if (!is_array($this->_data)) { $this->_data = array($this->_data); } $this->_data[] = $data; } } /** * Add an embedded document * * @param string $rel The relation of the embedded document to its container document * @param Document $document The document to add * @param boolean $overwrite Should I overwrite existing data with the same relation? * * @return boolean */ public function addEmbedded($rel, Document $document, $overwrite = true) { if (!array_key_exists($rel, $this->_embedded) || $overwrite) { $this->_embedded[$rel] = $document; return true; } elseif (array_key_exists($rel, $this->_embedded) && !$overwrite) { if (!is_array($this->_embedded[$rel])) { $this->_embedded[$rel] = array($this->_embedded[$rel]); } $this->_embedded[$rel][] = $document; return true; } else { return false; } } /** * Returns the collection of links of this document * * @param string $rel The relation of the links to fetch. Skip to get all links. * * @return array */ public function getLinks($rel = null) { return $this->_links->getLinks($rel); } /** * Returns the collection of embedded documents * * @param string $rel Optional; the relation to return the embedded documents for * * @return array|Document */ public function getEmbedded($rel = null) { if (empty($rel)) { return $this->_embedded; } elseif (isset($this->_embedded[$rel])) { return $this->_embedded[$rel]; } else { return array(); } } /** * Return the data attached to this document * * @return array|\stdClass */ public function getData() { return $this->_data; } /** * Instantiate and call a suitable renderer class to render this document * into the specified format. * * @param string $format The format to render the document into, e.g. 'json' * * @return string The rendered document * * @throws \LogicException If the format is unknown, i.e. there is no suitable renderer */ public function render($format = 'json') { $class_name = '\\FOF30\\Hal\\Render\\' . ucfirst($format); if (!class_exists($class_name, true)) { throw new InvalidRenderFormat($format); } /** @var RenderInterface $renderer */ $renderer = new $class_name($this); return $renderer->render( array( 'data_key' => $this->_dataKey ) ); } } Hal/Link.php000064400000006241152325653720006673 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Hal; use FOF30\Hal\Exception\InvalidLinkFormat; defined('_JEXEC') or die; /** * Implementation of the Hypertext Application Language link in PHP. * * @see http://stateless.co/hal_specification.html * * @property $href string * @property $templated bool * @property $name string * @property $hreflang string */ class Link { /** * For indicating the target URI. Corresponds with the ’Target IRI’ as * defined in Web Linking (RFC 5988). This attribute MAY contain a URI * Template (RFC6570) and in which case, SHOULD be complemented by an * additional templated attribute on the link with a boolean value true. * * @var string */ protected $_href = ''; /** * This attribute SHOULD be present with a boolean value of true when the * href of the link contains a URI Template (RFC6570). * * @var boolean */ protected $_templated = false; /** * For distinguishing between Resource and Link elements that share the * same relation * * @var string */ protected $_name = null; /** * For indicating what the language of the result of dereferencing the link should be. * * @var string */ protected $_hreflang = null; /** * For labeling the destination of a link with a human-readable identifier. * * @var string */ protected $_title = null; /** * Public constructor of a FOFHalLink object * * @param string $href See $this->_href * @param boolean $templated See $this->_templated * @param string $name See $this->_name * @param string $hreflang See $this->_hreflang * @param string $title See $this->_title * * @throws \InvalidArgumentException If $href is empty */ public function __construct($href, $templated = false, $name = null, $hreflang = null, $title = null) { if (empty($href)) { throw new InvalidLinkFormat; } $this->_href = $href; $this->_templated = $templated; $this->_name = $name; $this->_hreflang = $hreflang; $this->_title = $title; } /** * Is this a valid link? Checks the existence of required fields, not their * values. * * @return boolean */ public function check() { return !empty($this->_href); } /** * Magic getter for the protected properties * * @param string $name The name of the property to retrieve, sans the underscore * * @return mixed Null will always be returned if the property doesn't exist */ public function __get($name) { $property = '_' . $name; if (property_exists($this, $property)) { return $this->$property; } else { return null; } } /** * Magic setter for the protected properties * * @param string $name The name of the property to set, sans the underscore * @param mixed $value The value of the property to set * * @return void */ public function __set($name, $value) { if (($name == 'href') && empty($value)) { return; } $property = '_' . $name; if (property_exists($this, $property)) { $this->$property = $value; } } } Hal/Links.php000064400000005636152325653720007065 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Hal; defined('_JEXEC') or die; /** * Implementation of the Hypertext Application Language links in PHP. This is * actually a collection of links. * * @see http://stateless.co/hal_specification.html */ class Links { /** * The collection of links, sorted by relation * * @var array */ private $_links = array(); /** * Add a single link to the links collection * * @param string $rel The relation of the link to the document. See RFC 5988 * http://tools.ietf.org/html/rfc5988#section-6.2.2 A document * MUST always have a "self" link. * @param Link $link The actual link object * @param boolean $overwrite When false and a link of $rel relation exists, an array of * links is created. Otherwise the existing link is overwriten * with the new one * * @return boolean True if the link was added to the collection */ public function addLink($rel, Link $link, $overwrite = true) { if (!$link->check()) { return false; } if (!array_key_exists($rel, $this->_links) || $overwrite) { $this->_links[$rel] = $link; } else { if (!is_array($this->_links[$rel])) { $this->_links[$rel] = array($this->_links[$rel]); } $this->_links[$rel][] = $link; } } /** * Add multiple links to the links collection * * @param string $rel The relation of the links to the document. See RFC 5988. * @param array $links An array of FOFHalLink objects * @param boolean $overwrite When false and a link of $rel relation exists, an array * of links is created. Otherwise the existing link is * overwriten with the new one * * @return boolean True if the link was added to the collection */ public function addLinks($rel, array $links, $overwrite = true) { if (empty($links)) { return false; } $localOverwrite = $overwrite; foreach ($links as $link) { if ($link instanceof Link) { $this->addLink($rel, $link, $localOverwrite); } // After the first time we call this with overwrite on we have to // turn it off so that the other links are added to the set instead // of overwriting the first item that's already added. if ($localOverwrite) { $localOverwrite = false; } } } /** * Returns the collection of links * * @param string $rel Optional; the relation to return the links for * * @return array|Link */ public function getLinks($rel = null) { if (empty($rel)) { return $this->_links; } elseif (isset($this->_links[$rel])) { return $this->_links[$rel]; } else { return array(); } } } Inflector/Inflector.php000064400000031337152325653720011150 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Inflector; defined('_JEXEC') or die; /** * An Inflector to pluralize and singularize English nouns. */ class Inflector { /** * Rules for pluralizing and singularizing of nouns. * * @var array */ protected $rules = array ( // Pluralization rules. The regex on the left transforms to the regex on the right. 'pluralization' => array( '/move$/i' => 'moves', '/sex$/i' => 'sexes', '/child$/i' => 'children', '/children$/i' => 'children', '/man$/i' => 'men', '/men$/i' => 'men', '/foot$/i' => 'feet', '/feet$/i' => 'feet', '/person$/i' => 'people', '/people$/i' => 'people', '/taxon$/i' => 'taxa', '/taxa$/i' => 'taxa', '/(quiz)$/i' => '$1zes', '/^(ox)$/i' => '$1en', '/oxen$/i' => 'oxen', '/(m|l)ouse$/i' => '$1ice', '/(m|l)ice$/i' => '$1ice', '/(matr|vert|ind|suff)ix|ex$/i' => '$1ices', '/(x|ch|ss|sh)$/i' => '$1es', '/([^aeiouy]|qu)y$/i' => '$1ies', '/(?:([^f])fe|([lr])f)$/i' => '$1$2ves', '/sis$/i' => 'ses', '/([ti]|addend)um$/i' => '$1a', '/([ti]|addend)a$/i' => '$1a', '/(alumn|formul)a$/i' => '$1ae', '/(alumn|formul)ae$/i' => '$1ae', '/(buffal|tomat|her)o$/i' => '$1oes', '/(bu)s$/i' => '$1ses', '/(campu)s$/i' => '$1ses', '/(alias|status)$/i' => '$1es', '/(octop|vir)us$/i' => '$1i', '/(octop|vir)i$/i' => '$1i', '/(gen)us$/i' => '$1era', '/(gen)era$/i' => '$1era', '/(ax|test)is$/i' => '$1es', '/s$/i' => 's', '/$/' => 's', ), // Singularization rules. The regex on the left transforms to the regex on the right. 'singularization' => array( '/cookies$/i' => 'cookie', '/moves$/i' => 'move', '/sexes$/i' => 'sex', '/children$/i' => 'child', '/men$/i' => 'man', '/feet$/i' => 'foot', '/people$/i' => 'person', '/taxa$/i' => 'taxon', '/databases$/i' => 'database', '/menus$/i' => 'menu', '/(quiz)zes$/i' => '\1', '/(matr|suff)ices$/i' => '\1ix', '/(vert|ind|cod)ices$/i' => '\1ex', '/^(ox)en/i' => '\1', '/(alias|status)es$/i' => '\1', '/(tomato|hero|buffalo)es$/i' => '\1', '/([octop|vir])i$/i' => '\1us', '/(gen)era$/i' => '\1us', '/(cris|^ax|test)es$/i' => '\1is', '/is$/i' => 'is', '/us$/i' => 'us', '/ias$/i' => 'ias', '/(shoe)s$/i' => '\1', '/(o)es$/i' => '\1e', '/(bus)es$/i' => '\1', '/(campus)es$/i' => '\1', '/([m|l])ice$/i' => '\1ouse', '/(x|ch|ss|sh)es$/i' => '\1', '/(m)ovies$/i' => '\1ovie', '/(s)eries$/i' => '\1eries', '/(v)ies$/i' => '\1ie', '/([^aeiouy]|qu)ies$/i' => '\1y', '/([lr])ves$/i' => '\1f', '/(tive)s$/i' => '\1', '/(hive)s$/i' => '\1', '/([^f])ves$/i' => '\1fe', '/(^analy)ses$/i' => '\1sis', '/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis', '/([ti]|addend)a$/i' => '\1um', '/(alumn|formul)ae$/i' => '$1a', '/(n)ews$/i' => '\1ews', '/(.*)ss$/i' => '\1ss', '/(.*)s$/i' => '\1', ), // Uncountable objects are always singular 'uncountable' => array( 'aircraft', 'cannon', 'deer', 'equipment', 'fish', 'information', 'money', 'moose', 'news', 'rice', 'series', 'sheep', 'species', 'swine', ) ); /** * Cache of pluralized and singularized nouns. * * @var array */ protected $cache = array( 'singularized' => array(), 'pluralized' => array() ); public function deleteCache() { $this->cache['pluralized'] = array(); $this->cache['singularized'] = array(); } /** * Add a word to the cache, useful to make exceptions or to add words in other languages. * * @param string $singular word. * @param string $plural word. * * @return void */ public function addWord($singular, $plural) { $this->cache['pluralized'][$singular] = $plural; $this->cache['singularized'][$plural] = $singular; } /** * Singular English word to plural. * * @param string $word word to pluralize. * * @return string Plural noun. */ public function pluralize($word) { // Get the cached noun of it exists if (isset($this->cache['pluralized'][$word])) { return $this->cache['pluralized'][$word]; } // Check if the noun is already in plural form, i.e. in the singularized cache if (isset($this->cache['singularized'][$word])) { return $word; } // Create the plural noun if (in_array($word, $this->rules['uncountable'])) { $_cache['pluralized'][$word] = $word; return $word; } foreach ($this->rules['pluralization'] as $regexp => $replacement) { $matches = null; $plural = preg_replace($regexp, $replacement, $word, -1, $matches); if ($matches > 0) { $_cache['pluralized'][$word] = $plural; return $plural; } } return $word; } /** * Plural English word to singular. * * @param string $word Word to singularize. * * @return string Singular noun. */ public function singularize($word) { // Get the cached noun of it exists if (isset($this->cache['singularized'][$word])) { return $this->cache['singularized'][$word]; } // Check if the noun is already in singular form, i.e. in the pluralized cache if (isset($this->cache['pluralized'][$word])) { return $word; } // Create the singular noun if (in_array($word, $this->rules['uncountable'])) { $_cache['singularized'][$word] = $word; return $word; } foreach ($this->rules['singularization'] as $regexp => $replacement) { $matches = null; $singular = preg_replace($regexp, $replacement, $word, -1, $matches); if ($matches > 0) { $_cache['singularized'][$word] = $singular; return $singular; } } return $word; } /** * Returns given word as CamelCased. * * Converts a word like "foo_bar" or "foo bar" to "FooBar". It * will remove non alphanumeric characters from the word, so * "who's online" will be converted to "WhoSOnline" * * @param string $word Word to convert to camel case. * * @return string UpperCamelCasedWord */ public function camelize($word) { $word = preg_replace('/[^a-zA-Z0-9\s]/', ' ', $word); $word = str_replace(' ', '', ucwords(strtolower(str_replace('_', ' ', $word)))); return $word; } /** * Converts a word "into_it_s_underscored_version" * * Convert any "CamelCased" or "ordinary Word" into an "underscored_word". * * @param string $word Word to underscore * * @return string Underscored word */ public function underscore($word) { $word = preg_replace('/(\s)+/', '_', $word); $word = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $word)); return $word; } /** * Convert any "CamelCased" word into an array of strings * * Returns an array of strings each of which is a substring of string formed * by splitting it at the camelcased letters. * * @param string $word Word to explode * * @return array Array of strings */ public function explode($word) { $result = explode('_', self::underscore($word)); return $result; } /** * Convert an array of strings into a "CamelCased" word. * * @param array $words Array to implode * * @return string UpperCamelCasedWord */ public function implode($words) { $result = self::camelize(implode('_', $words)); return $result; } /** * Returns a human-readable string from $word. * * Returns a human-readable string from $word, by replacing * underscores with a space, and by upper-casing the initial * character by default. * * @param string $word String to "humanize" * * @return string Human-readable word */ public function humanize($word) { $result = ucwords(strtolower(str_replace("_", " ", $word))); return $result; } /** * Returns camelBacked version of a string. Same as camelize but first char is lowercased. * * @param string $string String to be camelBacked. * * @return string * * @see camelize */ public function variablize($string) { $string = self::camelize(self::underscore($string)); $result = strtolower(substr($string, 0, 1)); $variable = preg_replace('/\\w/', $result, $string, 1); return $variable; } /** * Check to see if an English word is singular * * @param string $string The word to check * * @return boolean */ public function isSingular($string) { // Check cache assuming the string is plural. $singular = isset($this->cache['singularized'][$string]) ? $this->cache['singularized'][$string] : null; $plural = $singular && isset($this->cache['pluralized'][$singular]) ? $this->cache['pluralized'][$singular] : null; if ($singular && $plural) { return $plural != $string; } // If string is not in the cache, try to pluralize and singularize it. return self::singularize(self::pluralize($string)) == $string; } /** * Check to see if an Enlish word is plural. * * @param string $string String to be checked. * * @return boolean */ public function isPlural($string) { // Uncountable objects are always singular (e.g. information) if (in_array($string, $this->rules['uncountable'])) { return false; } // Check cache assuming the string is singular. $plural = isset($this->cache['pluralized'][$string]) ? $this->cache['pluralized'][$string] : null; $singular = $plural && isset($this->cache['singularized'][$plural]) ? $this->cache['singularized'][$plural] : null; if ($plural && $singular) { return $singular != $string; } // If string is not in the cache, try to singularize and pluralize it. return self::pluralize(self::singularize($string)) == $string; } /** * Gets a part of a CamelCased word by index. * * Use a negative index to start at the last part of the word (-1 is the * last part) * * @param string $string Word * @param integer $index Index of the part * @param string $default Default value * * @return string */ public function getPart($string, $index, $default = null) { $parts = self::explode($string); if ($index < 0) { $index = count($parts) + $index; } return isset($parts[$index]) ? $parts[$index] : $default; } } Input/Input.php000064400000011073152325653720007467 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Input; defined('_JEXEC') or die; class Input extends \JInput { /** * Public constructor. Overridden to allow specifying the global input array * to use as a string and instantiate from an object holding variables. * * @param array|string|object|null $source Source data; set null to use $_REQUEST * @param array $options Filter options */ public function __construct($source = null, array $options = array()) { $hash = null; if (is_string($source)) { $hash = strtoupper($source); switch ($hash) { case 'GET': $source = $_GET; break; case 'POST': $source = $_POST; break; case 'FILES': $source = $_FILES; break; case 'COOKIE': $source = $_COOKIE; break; case 'ENV': $source = $_ENV; break; case 'SERVER': $source = $_SERVER; break; default: $source = $_REQUEST; $hash = 'REQUEST'; break; } } elseif (is_object($source) && ($source instanceof Input)) { $source = $source->getData(); } elseif (is_object($source) && ($source instanceof \JInput)) { $serialised = $source->serialize(); list ($xOptions, $xData, $xInput) = unserialize($serialised); unset ($xOptions); unset ($xInput); unset ($source); $source = $xData; unset ($xData); } elseif (is_object($source)) { try { $source = (array) $source; } catch (\Exception $exc) { $source = null; } } elseif (is_array($source)) { // Nothing, it's already an array } else { // Any other case $source = null; } // If we are not sure use the REQUEST array if (empty($source)) { $source = $_REQUEST; $hash = 'REQUEST'; } // Magic quotes GPC handling (something JInput simply can't handle at all) // @codeCoverageIgnoreStart if (($hash == 'REQUEST') && get_magic_quotes_gpc() && class_exists('\\JRequest', true)) { $source = \JRequest::get('REQUEST', 2); } // @codeCoverageIgnoreEnd parent::__construct($source, $options); } /** * Gets a value from the input data. Overridden to allow specifying a filter * mask. * * @param string $name Name of the value to get. * @param mixed $default Default value to return if variable does not exist. * @param string $filter Filter to apply to the value. * @param int $mask The filter mask * * @return mixed The filtered input value. */ public function get($name, $default = null, $filter = 'cmd', $mask = 0) { if (isset($this->data[$name])) { return $this->_cleanVar($this->data[$name], $mask, $filter); } return $default; } /** * Returns a copy of the raw data stored in the class * * @return array */ public function getData() { return $this->data; } /** * Magic method to get filtered input data. * * @param mixed $name Name of the value to get. * @param string $arguments [0] The name of the variable [1] The default value [2] Mask * * @return boolean The filtered boolean input value. */ public function __call($name, $arguments) { if (substr($name, 0, 3) == 'get') { $filter = substr($name, 3); $default = null; $mask = 0; if (isset($arguments[1])) { $default = $arguments[1]; } if (isset($arguments[2])) { $mask = $arguments[2]; } return $this->get($arguments[0], $default, $filter, $mask); } } /** * Custom filter implementation. Works better with arrays and allows the use * of a filter mask. * * @param mixed $var The variable (value) to clean * @param integer $mask The clean mask * @param string $type The variable type * * @return mixed */ protected function _cleanVar($var, $mask = 0, $type = null) { if (is_array($var)) { $temp = array(); foreach ($var as $k => $v) { $temp[$k] = self::_cleanVar($v, $mask); } return $temp; } // If the no trim flag is not set, trim the variable if (!($mask & 1) && is_string($var)) { $var = trim($var); } // Now we handle input filtering if ($mask & 2) { // If the allow raw flag is set, do not modify the variable } elseif ($mask & 4) { // If the allow HTML flag is set, apply a safe HTML filter to the variable $safeHtmlFilter = \JFilterInput::getInstance(null, null, 1, 1); $var = $safeHtmlFilter->clean($var, $type); } else { $var = $this->filter->clean($var, $type); } return $var; } } Layout/LayoutFile.php000064400000004230152325653720010620 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Layout; use FOF30\Container\Container; use JLayoutFile; defined('_JEXEC') or die; /** * Base class for rendering a display layout * loaded from from a layout file * * This class searches for Joomla! version override Layouts. For example, * if you have run this under Joomla! 3.0 and you try to load * mylayout.default it will automatically search for the * layout files default.j30.php, default.j3.php and default.php, in this * order. * * @package FrameworkOnFramework */ class LayoutFile extends JLayoutFile { /** @var Container The component container */ public $container = null; /** * Method to finds the full real file path, checking possible overrides * * @return string The full path to the layout file */ protected function getPath() { if (is_null($this->container)) { $component = $this->options->get('component'); $this->container = Container::getInstance($component); } $filesystem = $this->container->filesystem; if (is_null($this->fullPath) && !empty($this->layoutId)) { $parts = explode('.', $this->layoutId); $file = array_pop($parts); $filePath = implode('/', $parts); $suffixes = $this->container->platform->getTemplateSuffixes(); foreach ($suffixes as $suffix) { $files[] = $file . $suffix . '.php'; } $files[] = $file . '.php'; $platformDirs = $this->container->platform->getPlatformBaseDirs(); $prefix = $this->container->platform->isBackend() ? $platformDirs['admin'] : $platformDirs['root']; $possiblePaths = array( $prefix . '/templates/' . $this->container->platform->getTemplate() . '/html/layouts/' . $filePath, $this->basePath . '/' . $filePath, $platformDirs['root'] . '/layouts/' . $filePath, ); reset($files); foreach ($files as $fileName) { if (!is_null($this->fullPath)) { break; } $r = $filesystem->pathFind($possiblePaths, $fileName); $this->fullPath = $r === false ? null : $r; } } return $this->fullPath; } } Layout/LayoutHelper.php000064400000002627152325653720011170 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Layout; use FOF30\Container\Container; defined('_JEXEC') or die; class LayoutHelper { /** * A default base path that will be used if none is provided when calling the render method. * Note that JLayoutFile itself will defaults to JPATH_ROOT . '/layouts' if no basePath is supplied at all * * @var string */ public static $defaultBasePath = ''; /** * Method to render the layout. * * @param Container $container The container of your component * @param string $layoutFile Dot separated path to the layout file, relative to base path * @param object $displayData Object which properties are used inside the layout file to build displayed output * @param string $basePath Base path to use when loading layout files * * @return string */ public static function render(Container $container, $layoutFile, $displayData = null, $basePath = '') { $basePath = empty($basePath) ? self::$defaultBasePath : $basePath; // Make sure we send null to LayoutFile if no path set $basePath = empty($basePath) ? null : $basePath; $layout = new LayoutFile($layoutFile, $basePath); $layout->container = $container; $renderedLayout = $layout->render($displayData); return $renderedLayout; } } Less/Formatter/Classic.php000064400000006330152325653720011523 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Less\Formatter; defined('_JEXEC') or die; /** * This class is taken verbatim from: * * lessphp v0.3.9 * http://leafo.net/lessphp * * LESS css compiler, adapted from http://lesscss.org * * Copyright 2012, Leaf Corcoran <leafot@gmail.com> * Licensed under MIT or GPLv3, see LICENSE * * @since 2.0 */ class 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 constructor */ public function __construct() { $this->indentLevel = 0; } /** * Indent a string by $n positions * * @param integer $n How many positions to indent * * @return string The indented string */ public function indentStr($n = 0) { return str_repeat($this->indentChar, max($this->indentLevel + $n, 0)); } /** * Return the code for a property * * @param string $name The name of the porperty * @param string $value The value of the porperty * * @return string The CSS code */ public function property($name, $value) { return $name . $this->assignSeparator . $value . ";"; } /** * Is a block empty? * * @param \stdClass $block The block to check * * @return boolean True if the block has no lines or children */ protected function isEmpty($block) { if (empty($block->lines)) { foreach ($block->children as $child) { if (!$this->isEmpty($child)) { return false; } } return true; } return false; } /** * Output a CSS block * * @param \stdClass $block The block definition to output * * @return void */ 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--; } } } Less/Formatter/Compressed.php000064400000001611152325653720012243 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Less\Formatter; defined('_JEXEC') or die; /** * This class is taken verbatim from: * * lessphp v0.3.9 * http://leafo.net/lessphp * * LESS css compiler, adapted from http://lesscss.org * * Copyright 2012, Leaf Corcoran <leafot@gmail.com> * Licensed under MIT or GPLv3, see LICENSE * * @since 2.0 */ class Compressed extends Classic { public $disableSingle = true; public $open = "{"; public $selectorSeparator = ","; public $assignSeparator = ":"; public $break = ""; public $compressColors = true; /** * Indent a string by $n positions * * @param integer $n How many positions to indent * * @return string The indented string */ public function indentStr($n = 0) { return ""; } } Less/Formatter/Joomla.php000064400000001237152325653720011364 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Less\Formatter; defined('_JEXEC') or die; /** * This class is based on: * * lessphp v0.3.9 * http://leafo.net/lessphp * * LESS css compiler, adapted from http://lesscss.org * * Copyright 2012, Leaf Corcoran <leafot@gmail.com> * Licensed under MIT or GPLv3, see LICENSE * * @since 2.1 */ class Joomla extends Classic { public $disableSingle = true; public $breakSelectors = true; public $assignSeparator = ": "; public $selectorSeparator = ","; public $indentChar = "\t"; } Less/Formatter/Lessjs.php000064400000001175152325653720011407 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Less\Formatter; defined('_JEXEC') or die; /** * This class is taken verbatim from: * * lessphp v0.3.9 * http://leafo.net/lessphp * * LESS css compiler, adapted from http://lesscss.org * * Copyright 2012, Leaf Corcoran <leafot@gmail.com> * Licensed under MIT or GPLv3, see LICENSE * * @since 2.0 */ class Lessjs { public $disableSingle = true; public $breakSelectors = true; public $assignSeparator = ": "; public $selectorSeparator = ","; } Less/Parser/Parser.php000064400000115763152325653720010702 0ustar00<?php /** * @package FOF * @copyright Copyright (c)2010-2019 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Less\Parser; use FOF30\Less\Less; use Exception; defined('_JEXEC') or die; /** * This class is taken verbatim from: * * lessphp v0.3.9 * http://leafo.net/lessphp * * LESS css compiler, adapted from http://lesscss.org * * Copyright 2012, Leaf Corcoran <leafot@gmail.com> * Licensed under MIT or GPLv3, see LICENSE * * Responsible for taking a string of LESS code and converting it into a syntax tree * * @since 2.0 */ class Parser { // Used to uniquely identify blocks protected static $nextBlockId = 0; protected static $precedence = array( '=<' => 0, '>=' => 0, '=' => 0, '<' => 0, '>' => 0, '+' => 1, '-' => 1, '*' => 2, '/' => 2, '%' => 2, ); protected static $whitePattern; protected static $commentMulti; protected static $commentSingle = "//"; protected static $commentMultiLeft = "/*"; protected static $commentMultiRight = "*/"; // Regex string to match any of the operators protected static $operatorString; // These properties will supress division unless it's inside parenthases protected static $supressDivisionProps = array('/border-radius$/i', '/^font$/i'); protected $blockDirectives = array("font-face", "keyframes", "page", "-moz-document"); protected $lineDirectives = array("charset"); /** * if we are in parens we can be more liberal with whitespace around * operators because it must resolve to a single value and thus is less * ambiguous. * * Consider: * property1: 10 -5; // is two numbers, 10 and -5 * property2: (10 -5); // should resolve to 5 */ protected $inParens = false; // Caches preg escaped literals protected static $literalCache = array(); /** * Constructor * * @param [type] $lessc [description] * @param string $sourceName [description] */ public function __cons
/home/digilove/public_html/modules/mod_marketplacemenus/../../41423/fof30.tar