Файловый менеджер - Редактировать - /home/poliximo/public_html/da45a/twofactorauth.zip
Назад
PK ���\��; ; totp/postinstall/actions.phpnu �[��� <?php /** * @package Joomla.Plugin * @subpackage Twofactorauth.totp * * @copyright Copyright (C) 2005 - 2019 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 concerning the activation of the * two-factor authentication code. */ /** * Checks if the plugin is enabled. If not it returns true, meaning that the * message concerning two factor authentication should be displayed. * * @return integer * * @since 3.2 */ function twofactorauth_postinstall_condition() { $db = JFactory::getDbo(); $query = $db->getQuery(true) ->select('*') ->from($db->qn('#__extensions')) ->where($db->qn('type') . ' = ' . $db->q('plugin')) ->where($db->qn('enabled') . ' = ' . $db->q('1')) ->where($db->qn('folder') . ' = ' . $db->q('twofactorauth')); $db->setQuery($query); $enabled_plugins = $db->loadObjectList(); return count($enabled_plugins) === 0; } /** * Enables the two factor authentication plugin and redirects the user to their * user profile page so that they can enable two factor authentication on their * account. * * @return void * * @since 3.2 */ function twofactorauth_postinstall_action() { // Enable the plugin $db = JFactory::getDbo(); $query = $db->getQuery(true) ->update($db->qn('#__extensions')) ->set($db->qn('enabled') . ' = ' . $db->q(1)) ->where($db->qn('type') . ' = ' . $db->q('plugin')) ->where($db->qn('folder') . ' = ' . $db->q('twofactorauth')); $db->setQuery($query); $db->execute(); // Redirect the user to their profile editor page $url = 'index.php?option=com_users&task=user.edit&id=' . JFactory::getUser()->id; JFactory::getApplication()->redirect($url); } PK ���\�� � totp/tmpl/form.phpnu �[��� <?php /** * @package Joomla.Plugin * @subpackage Twofactorauth.totp.tmpl * * @copyright Copyright (C) 2005 - 2019 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\HTML\HTMLHelper; use Joomla\CMS\Factory; HTMLHelper::_('script', 'plg_twofactorauth_totp/qrcode.min.js', array('version' => 'auto', 'relative' => true)); $js = " (function(document) { document.addEventListener('DOMContentLoaded', function() { var qr = qrcode(0, 'H'); qr.addData('" . $url . "'); qr.make(); document.getElementById('totp-qrcode').innerHTML = qr.createImgTag(4); }); })(document); "; Factory::getDocument()->addScriptDeclaration($js); ?> <input type="hidden" name="jform[twofactor][totp][key]" value="<?php echo $secret ?>" /> <div class="well"> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_INTRO') ?> </div> <fieldset> <legend> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_HEAD') ?> </legend> <p> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_TEXT') ?> </p> <ul> <li> <a href="<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_ITEM1_LINK') ?>" target="_blank" rel="noopener noreferrer"> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_ITEM1') ?> </a> </li> <li> <a href="<?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_ITEM2_LINK') ?>" target="_blank" rel="noopener noreferrer"> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_ITEM2') ?> </a> </li> </ul> <div class="alert"> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP1_WARN') ?> </div> </fieldset> <fieldset> <legend> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_HEAD') ?> </legend> <div class="span6"> <p> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_TEXT') ?> </p> <table class="table table-striped"> <tr> <td> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_ACCOUNT') ?> </td> <td> <?php echo $username ?>@<?php echo $hostname ?> </td> </tr> <tr> <td> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_KEY') ?> </td> <td> <?php echo $secret ?> </td> </tr> </table> </div> <div class="span6"> <p> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_ALTTEXT') ?> <br /> <div id="totp-qrcode"></div> </p> </div> <div class="clearfix"></div> <div class="alert alert-info"> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP2_RESET') ?> </div> </fieldset> <?php if ($new_totp): ?> <fieldset> <legend> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP3_HEAD') ?> </legend> <p> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP3_TEXT') ?> </p> <div class="control-group"> <label class="control-label" for="totpsecuritycode"> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_STEP3_SECURITYCODE') ?> </label> <div class="controls"> <input type="text" class="input-small" name="jform[twofactor][totp][securitycode]" id="totpsecuritycode" autocomplete="0"> </div> </div> </fieldset> <?php endif; ?> PK ���\�Ku� � totp/totp.xmlnu �[��� <?xml version="1.0" encoding="utf-8"?> <extension version="3.1" type="plugin" group="system" method="upgrade"> <name>plg_twofactorauth_totp</name> <author>Joomla! Project</author> <creationDate>August 2013</creationDate> <copyright>Copyright (C) 2005 - 2019 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.0</version> <description>PLG_TWOFACTORAUTH_TOTP_XML_DESCRIPTION</description> <files> <filename plugin="totp">totp.php</filename> <folder>postinstall</folder> <folder>tmpl</folder> </files> <languages> <language tag="en-GB">en-GB.plg_twofactorauth_totp.ini</language> <language tag="en-GB">en-GB.plg_twofactorauth_totp.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> <field name="section" type="radio" label="PLG_TWOFACTORAUTH_TOTP_SECTION_LABEL" description="PLG_TWOFACTORAUTH_TOTP_SECTION_DESC" default="3" filter="integer" class="btn-group" > <option value="1">PLG_TWOFACTORAUTH_TOTP_SECTION_SITE</option> <option value="2">PLG_TWOFACTORAUTH_TOTP_SECTION_ADMIN</option> <option value="3">PLG_TWOFACTORAUTH_TOTP_SECTION_BOTH</option> </field> </fieldset> </fields> </config> </extension> PK ���\WǨ�1 1 totp/totp.phpnu �[��� <?php /** * @package Joomla.Plugin * @subpackage Twofactorauth.totp * * @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Joomla! Two Factor Authentication using Google Authenticator TOTP Plugin * * @since 3.2 */ class PlgTwofactorauthTotp extends JPlugin { /** * Affects constructor behavior. If true, language files will be loaded automatically. * * @var boolean * @since 3.2 */ protected $autoloadLanguage = true; /** * Method name * * @var string * @since 3.2 */ protected $methodName = 'totp'; /** * This method returns the identification object for this two factor * authentication plugin. * * @return stdClass An object with public properties method and title * * @since 3.2 */ public function onUserTwofactorIdentify() { $section = (int) $this->params->get('section', 3); $current_section = 0; try { $app = JFactory::getApplication(); if ($app->isClient('administrator')) { $current_section = 2; } elseif ($app->isClient('site')) { $current_section = 1; } } catch (Exception $exc) { $current_section = 0; } if (!($current_section & $section)) { return false; } return (object) array( 'method' => $this->methodName, 'title' => JText::_('PLG_TWOFACTORAUTH_TOTP_METHOD_TITLE') ); } /** * Shows the configuration page for this two factor authentication method. * * @param object $otpConfig The two factor auth configuration object * @param integer $user_id The numeric user ID of the user whose form we'll display * * @return boolean|string False if the method is not ours, the HTML of the configuration page otherwise * * @see UsersModelUser::getOtpConfig * @since 3.2 */ public function onUserTwofactorShowConfiguration($otpConfig, $user_id = null) { // Create a new TOTP class with Google Authenticator compatible settings $totp = new FOFEncryptTotp(30, 6, 10); if ($otpConfig->method === $this->methodName) { // This method is already activated. Reuse the same secret key. $secret = $otpConfig->config['code']; } else { // This methods is not activated yet. Create a new secret key. $secret = $totp->generateSecret(); } // These are used by Google Authenticator to tell accounts apart $username = JFactory::getUser($user_id)->username; $hostname = JUri::getInstance()->getHost(); // This is the URL to the QR code for Google Authenticator $url = sprintf("otpauth://totp/%s@%s?secret=%s", $username, $hostname, $secret); // Is this a new TOTP setup? If so, we'll have to show the code validation field. $new_totp = $otpConfig->method !== 'totp'; // Start output buffering @ob_start(); // Include the form.php from a template override. If none is found use the default. $path = FOFPlatform::getInstance()->getTemplateOverridePath('plg_twofactorauth_totp', true); JLoader::import('joomla.filesystem.file'); if (JFile::exists($path . '/form.php')) { include_once $path . '/form.php'; } else { include_once __DIR__ . '/tmpl/form.php'; } // Stop output buffering and get the form contents $html = @ob_get_clean(); // Return the form contents return array( 'method' => $this->methodName, 'form' => $html ); } /** * The save handler of the two factor configuration method's configuration * page. * * @param string $method The two factor auth method for which we'll show the config page * * @return boolean|stdClass False if the method doesn't match or we have an error, OTP config object if it succeeds * * @see UsersModelUser::setOtpConfig * @since 3.2 */ public function onUserTwofactorApplyConfiguration($method) { if ($method !== $this->methodName) { return false; } // Get a reference to the input data object $input = JFactory::getApplication()->input; // Load raw data $rawData = $input->get('jform', array(), 'array'); if (!isset($rawData['twofactor']['totp'])) { return false; } $data = $rawData['twofactor']['totp']; // Warn if the securitycode is empty if (array_key_exists('securitycode', $data) && empty($data['securitycode'])) { try { $app = JFactory::getApplication(); $app->enqueueMessage(JText::_('PLG_TWOFACTORAUTH_TOTP_ERR_VALIDATIONFAILED'), 'error'); } catch (Exception $exc) { // This only happens when we are in a CLI application. We cannot // enqueue a message, so just do nothing. } return false; } // Create a new TOTP class with Google Authenticator compatible settings $totp = new FOFEncryptTotp(30, 6, 10); // Check the security code entered by the user (exact time slot match) $code = $totp->getCode($data['key']); $check = $code === $data['securitycode']; /* * If the check fails, test the previous 30 second slot. This allow the * user to enter the security code when it's becoming red in Google * Authenticator app (reaching the end of its 30 second lifetime) */ if (!$check) { $time = time() - 30; $code = $totp->getCode($data['key'], $time); $check = $code === $data['securitycode']; } /* * If the check fails, test the next 30 second slot. This allows some * time drift between the authentication device and the server */ if (!$check) { $time = time() + 30; $code = $totp->getCode($data['key'], $time); $check = $code === $data['securitycode']; } if (!$check) { // Check failed. Do not change two factor authentication settings. return false; } // Check succeedeed; return an OTP configuration object $otpConfig = (object) array( 'method' => 'totp', 'config' => array( 'code' => $data['key'] ), 'otep' => array() ); return $otpConfig; } /** * This method should handle any two factor authentication and report back * to the subject. * * @param array $credentials Array holding the user credentials * @param array $options Array of extra options * * @return boolean True if the user is authorised with this two-factor authentication method * * @since 3.2 */ public function onUserTwofactorAuthenticate($credentials, $options) { // Get the OTP configuration object $otpConfig = $options['otp_config']; // Make sure it's an object if (empty($otpConfig) || !is_object($otpConfig)) { return false; } // Check if we have the correct method if ($otpConfig->method !== $this->methodName) { return false; } // Check if there is a security code if (empty($credentials['secretkey'])) { return false; } // Create a new TOTP class with Google Authenticator compatible settings $totp = new FOFEncryptTotp(30, 6, 10); // Check the code $code = $totp->getCode($otpConfig->config['code']); $check = $code === $credentials['secretkey']; /* * If the check fails, test the previous 30 second slot. This allow the * user to enter the security code when it's becoming red in Google * Authenticator app (reaching the end of its 30 second lifetime) */ if (!$check) { $time = time() - 30; $code = $totp->getCode($otpConfig->config['code'], $time); $check = $code === $credentials['secretkey']; } /* * If the check fails, test the next 30 second slot. This allows some * time drift between the authentication device and the server */ if (!$check) { $time = time() + 30; $code = $totp->getCode($otpConfig->config['code'], $time); $check = $code === $credentials['secretkey']; } return $check; } } PK ���\�&)XY! Y! yubikey/yubikey.phpnu �[��� <?php /** * @package Joomla.Plugin * @subpackage Twofactorauth.yubikey * * @copyright Copyright (C) 2005 - 2019 Open Source Matters, Inc. All rights reserved. * @license GNU General Public License version 2 or later; see LICENSE.txt */ defined('_JEXEC') or die; /** * Joomla! Two Factor Authentication using Yubikey Plugin * * @since 3.2 */ class PlgTwofactorauthYubikey extends JPlugin { /** * Affects constructor behavior. If true, language files will be loaded automatically. * * @var boolean * @since 3.2 */ protected $autoloadLanguage = true; /** * Method name * * @var string * @since 3.2 */ protected $methodName = 'yubikey'; /** * This method returns the identification object for this two factor * authentication plugin. * * @return stdClass An object with public properties method and title * * @since 3.2 */ public function onUserTwofactorIdentify() { $section = (int) $this->params->get('section', 3); $current_section = 0; try { $app = JFactory::getApplication(); if ($app->isClient('administrator')) { $current_section = 2; } elseif ($app->isClient('site')) { $current_section = 1; } } catch (Exception $exc) { $current_section = 0; } if (!($current_section & $section)) { return false; } return (object) array( 'method' => $this->methodName, 'title' => JText::_('PLG_TWOFACTORAUTH_YUBIKEY_METHOD_TITLE'), ); } /** * Shows the configuration page for this two factor authentication method. * * @param object $otpConfig The two factor auth configuration object * @param integer $user_id The numeric user ID of the user whose form we'll display * * @return boolean|string False if the method is not ours, the HTML of the configuration page otherwise * * @see UsersModelUser::getOtpConfig * @since 3.2 */ public function onUserTwofactorShowConfiguration($otpConfig, $user_id = null) { if ($otpConfig->method === $this->methodName) { // This method is already activated. Reuse the same Yubikey ID. $yubikey = $otpConfig->config['yubikey']; } else { // This methods is not activated yet. We'll need a Yubikey TOTP to setup this Yubikey. $yubikey = ''; } // Is this a new TOTP setup? If so, we'll have to show the code validation field. $new_totp = $otpConfig->method !== $this->methodName; // Start output buffering @ob_start(); // Include the form.php from a template override. If none is found use the default. $path = FOFPlatform::getInstance()->getTemplateOverridePath('plg_twofactorauth_yubikey', true); JLoader::import('joomla.filesystem.file'); if (JFile::exists($path . '/form.php')) { include_once $path . '/form.php'; } else { include_once __DIR__ . '/tmpl/form.php'; } // Stop output buffering and get the form contents $html = @ob_get_clean(); // Return the form contents return array( 'method' => $this->methodName, 'form' => $html, ); } /** * The save handler of the two factor configuration method's configuration * page. * * @param string $method The two factor auth method for which we'll show the config page * * @return boolean|stdClass False if the method doesn't match or we have an error, OTP config object if it succeeds * * @see UsersModelUser::setOtpConfig * @since 3.2 */ public function onUserTwofactorApplyConfiguration($method) { if ($method !== $this->methodName) { return false; } // Get a reference to the input data object $input = JFactory::getApplication()->input; // Load raw data $rawData = $input->get('jform', array(), 'array'); if (!isset($rawData['twofactor']['yubikey'])) { return false; } $data = $rawData['twofactor']['yubikey']; // Warn if the securitycode is empty if (array_key_exists('securitycode', $data) && empty($data['securitycode'])) { try { JFactory::getApplication()->enqueueMessage(JText::_('PLG_TWOFACTORAUTH_YUBIKEY_ERR_VALIDATIONFAILED'), 'error'); } catch (Exception $exc) { // This only happens when we are in a CLI application. We cannot // enqueue a message, so just do nothing. } return false; } // Validate the Yubikey OTP $check = $this->validateYubikeyOtp($data['securitycode']); if (!$check) { JFactory::getApplication()->enqueueMessage(JText::_('PLG_TWOFACTORAUTH_YUBIKEY_ERR_VALIDATIONFAILED'), 'error'); // Check failed. Do not change two factor authentication settings. return false; } // Remove the last 32 digits and store the rest in the user configuration parameters $yubikey = substr($data['securitycode'], 0, -32); // Check succeedeed; return an OTP configuration object $otpConfig = (object) array( 'method' => $this->methodName, 'config' => array( 'yubikey' => $yubikey ), 'otep' => array() ); return $otpConfig; } /** * This method should handle any two factor authentication and report back * to the subject. * * @param array $credentials Array holding the user credentials * @param array $options Array of extra options * * @return boolean True if the user is authorised with this two-factor authentication method * * @since 3.2 */ public function onUserTwofactorAuthenticate($credentials, $options) { // Get the OTP configuration object $otpConfig = $options['otp_config']; // Make sure it's an object if (empty($otpConfig) || !is_object($otpConfig)) { return false; } // Check if we have the correct method if ($otpConfig->method !== $this->methodName) { return false; } // Check if there is a security code if (empty($credentials['secretkey'])) { return false; } // Check if the Yubikey starts with the configured Yubikey user string $yubikey_valid = $otpConfig->config['yubikey']; $yubikey = substr($credentials['secretkey'], 0, -32); $check = $yubikey === $yubikey_valid; if ($check) { $check = $this->validateYubikeyOtp($credentials['secretkey']); } return $check; } /** * Validates a Yubikey OTP against the Yubikey servers * * @param string $otp The OTP generated by your Yubikey * * @return boolean True if it's a valid OTP * * @since 3.2 */ public function validateYubikeyOtp($otp) { $server_queue = array( 'api.yubico.com', 'api2.yubico.com', 'api3.yubico.com', 'api4.yubico.com', 'api5.yubico.com', ); shuffle($server_queue); $gotResponse = false; $check = false; $token = JSession::getFormToken(); $nonce = md5($token . uniqid(mt_rand())); while (!$gotResponse && !empty($server_queue)) { $server = array_shift($server_queue); $uri = new JUri('https://' . $server . '/wsapi/2.0/verify'); // I don't see where this ID is used? $uri->setVar('id', 1); // The OTP we read from the user $uri->setVar('otp', $otp); // This prevents a REPLAYED_OTP status of the token doesn't change // after a user submits an invalid OTP $uri->setVar('nonce', $nonce); // Minimum service level required: 50% (at least 50% of the YubiCloud // servers must reply positively for the OTP to validate) $uri->setVar('sl', 50); // Timeou waiting for YubiCloud servers to reply: 5 seconds. $uri->setVar('timeout', 5); try { $http = JHttpFactory::getHttp(); $response = $http->get($uri->toString(), null, 6); if (!empty($response)) { $gotResponse = true; } else { continue; } } catch (Exception $exc) { // No response, continue with the next server continue; } } // No server replied; we can't validate this OTP if (!$gotResponse) { return false; } // Parse response $lines = explode("\n", $response->body); $data = array(); foreach ($lines as $line) { $line = trim($line); $parts = explode('=', $line, 2); if (count($parts) < 2) { continue; } $data[$parts[0]] = $parts[1]; } // Validate the response - We need an OK message reply if ($data['status'] !== 'OK') { return false; } // Validate the response - We need a confidence level over 50% if ($data['sl'] < 50) { return false; } // Validate the response - The OTP must match if ($data['otp'] !== $otp) { return false; } // Validate the response - The token must match if ($data['nonce'] !== $nonce) { return false; } return true; } } PK ���\�˹�� � yubikey/yubikey.xmlnu �[��� <?xml version="1.0" encoding="utf-8"?> <extension version="3.1" type="plugin" group="system" method="upgrade"> <name>plg_twofactorauth_yubikey</name> <author>Joomla! Project</author> <creationDate>September 2013</creationDate> <copyright>Copyright (C) 2005 - 2019 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.0</version> <description>PLG_TWOFACTORAUTH_YUBIKEY_XML_DESCRIPTION</description> <files> <filename plugin="yubikey">yubikey.php</filename> <folder>tmpl</folder> </files> <languages> <language tag="en-GB">en-GB.plg_twofactorauth_yubikey.ini</language> <language tag="en-GB">en-GB.plg_twofactorauth_yubikey.sys.ini</language> </languages> <config> <fields name="params"> <fieldset name="basic"> <field name="section" type="radio" label="PLG_TWOFACTORAUTH_YUBIKEY_SECTION_LABEL" description="PLG_TWOFACTORAUTH_YUBIKEY_SECTION_DESC" default="3" filter="integer" class="btn-group" > <option value="1">PLG_TWOFACTORAUTH_YUBIKEY_SECTION_SITE</option> <option value="2">PLG_TWOFACTORAUTH_YUBIKEY_SECTION_ADMIN</option> <option value="3">PLG_TWOFACTORAUTH_YUBIKEY_SECTION_BOTH</option> </field> </fieldset> </fields> </config> </extension> PK ���\� kr r yubikey/tmpl/form.phpnu �[��� <?php /** * @package Joomla.Plugin * @subpackage Twofactorauth.yubikey.tmpl * * @copyright Copyright (C) 2005 - 2019 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="well"> <?php echo JText::_('PLG_TWOFACTORAUTH_YUBIKEY_INTRO') ?> </div> <?php if ($new_totp): ?> <fieldset> <legend> <?php echo JText::_('PLG_TWOFACTORAUTH_YUBIKEY_STEP1_HEAD') ?> </legend> <p> <?php echo JText::_('PLG_TWOFACTORAUTH_YUBIKEY_STEP1_TEXT') ?> </p> <div class="control-group"> <label class="control-label" for="yubikeysecuritycode"> <?php echo JText::_('PLG_TWOFACTORAUTH_YUBIKEY_SECURITYCODE') ?> </label> <div class="controls"> <input type="text" class="input-medium" name="jform[twofactor][yubikey][securitycode]" id="yubikeysecuritycode" autocomplete="0"> </div> </div> </fieldset> <?php else: ?> <fieldset> <legend> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_RESET_HEAD') ?> </legend> <p> <?php echo JText::_('PLG_TWOFACTORAUTH_TOTP_RESET_TEXT') ?> </p> </fieldset> <?php endif; ?> PK ���\��; ; totp/postinstall/actions.phpnu �[��� PK ���\�� � � totp/tmpl/form.phpnu �[��� PK ���\�Ku� � � totp/totp.xmlnu �[��� PK ���\WǨ�1 1 � totp/totp.phpnu �[��� PK ���\�&)XY! Y! �7 yubikey/yubikey.phpnu �[��� PK ���\�˹�� � �Y yubikey/yubikey.xmlnu �[��� PK ���\� kr r e_ yubikey/tmpl/form.phpnu �[��� PK C d
| ver. 1.4 |
Github
|
.
| PHP 8.3.31 | Генерация страницы: 0 |
proxy
|
phpinfo
|
Настройка