| Current Path : /home/wuectly/www/03cbe/ |
| Current File : /home/wuectly/www/03cbe/fof30.zip |
PK �%"]��<�t2 t2 Inflector/Inflector.phpnu &1i� <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 2, or later
*/
namespace FOF30\Inflector;
defined('_JEXEC') || die;
/**
* An Inflector to pluralize and singularize English nouns.
*/
class Inflector
{
/**
* Rules for pluralizing and singularizing of nouns.
*
* @var array
*/
protected $rules = [
// Pluralization rules. The regex on the left transforms to the regex on the right.
'pluralization' => [
'/move$/i' => 'moves',
'/sex$/i' => 'sexes',
'/child$/i' => 'children',
'/children$/i' => 'children',
'/man$/i' => 'men',
'/men$/i' => 'men',
'/foot$/i' => 'feet',
'/feet$/i' => 'feet',
'/person$/i' => 'people',
'/people$/i' => 'people',
'/taxon$/i' => 'taxa',
'/taxa$/i' => 'taxa',
'/(quiz)$/i' => '$1zes',
'/^(ox)$/i' => '$1en',
'/oxen$/i' => 'oxen',
'/(m|l)ouse$/i' => '$1ice',
'/(m|l)ice$/i' => '$1ice',
'/(matr|vert|ind|suff)ix|ex$/i' => '$1ices',
'/(x|ch|ss|sh)$/i' => '$1es',
'/([^aeiouy]|qu)y$/i' => '$1ies',
'/(?:([^f])fe|([lr])f)$/i' => '$1$2ves',
'/sis$/i' => 'ses',
'/([ti]|addend)um$/i' => '$1a',
'/([ti]|addend)a$/i' => '$1a',
'/(alumn|formul)a$/i' => '$1ae',
'/(alumn|formul)ae$/i' => '$1ae',
'/(buffal|tomat|her)o$/i' => '$1oes',
'/(bu)s$/i' => '$1ses',
'/(campu)s$/i' => '$1ses',
'/(alias|status)$/i' => '$1es',
'/(octop|vir)us$/i' => '$1i',
'/(octop|vir)i$/i' => '$1i',
'/(gen)us$/i' => '$1era',
'/(gen)era$/i' => '$1era',
'/(ax|test)is$/i' => '$1es',
'/s$/i' => 's',
'/$/' => 's',
],
// Singularization rules. The regex on the left transforms to the regex on the right.
'singularization' => [
'/cookies$/i' => 'cookie',
'/moves$/i' => 'move',
'/sexes$/i' => 'sex',
'/children$/i' => 'child',
'/men$/i' => 'man',
'/feet$/i' => 'foot',
'/people$/i' => 'person',
'/taxa$/i' => 'taxon',
'/databases$/i' => 'database',
'/menus$/i' => 'menu',
'/(quiz)zes$/i' => '\1',
'/(matr|suff)ices$/i' => '\1ix',
'/(vert|ind|cod)ices$/i' => '\1ex',
'/^(ox)en/i' => '\1',
'/(alias|status)es$/i' => '\1',
'/(tomato|hero|buffalo)es$/i' => '\1',
'/([octop|vir])i$/i' => '\1us',
'/(gen)era$/i' => '\1us',
'/(cris|^ax|test)es$/i' => '\1is',
'/is$/i' => 'is',
'/us$/i' => 'us',
'/ias$/i' => 'ias',
'/(shoe)s$/i' => '\1',
'/(o)es$/i' => '\1e',
'/(bus)es$/i' => '\1',
'/(campus)es$/i' => '\1',
'/([m|l])ice$/i' => '\1ouse',
'/(x|ch|ss|sh)es$/i' => '\1',
'/(m)ovies$/i' => '\1ovie',
'/(s)eries$/i' => '\1eries',
'/(v)ies$/i' => '\1ie',
'/([^aeiouy]|qu)ies$/i' => '\1y',
'/([lr])ves$/i' => '\1f',
'/(tive)s$/i' => '\1',
'/(hive)s$/i' => '\1',
'/([^f])ves$/i' => '\1fe',
'/(^analy)ses$/i' => '\1sis',
'/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i' => '\1\2sis',
'/([ti]|addend)a$/i' => '\1um',
'/(alumn|formul)ae$/i' => '$1a',
'/(n)ews$/i' => '\1ews',
'/(.*)ss$/i' => '\1ss',
'/(.*)s$/i' => '\1',
],
// Uncountable objects are always singular
'uncountable' => [
'aircraft',
'cannon',
'deer',
'equipment',
'fish',
'information',
'money',
'moose',
'news',
'rice',
'series',
'sheep',
'species',
'swine',
],
];
/**
* Cache of pluralized and singularized nouns.
*
* @var array
*/
protected $cache = [
'singularized' => [],
'pluralized' => [],
];
public function deleteCache()
{
$this->cache['pluralized'] = [];
$this->cache['singularized'] = [];
}
/**
* Add a word to the cache, useful to make exceptions or to add words in other languages.
*
* @param string $singular word.
* @param string $plural word.
*
* @return void
*/
public function addWord($singular, $plural)
{
$this->cache['pluralized'][$singular] = $plural;
$this->cache['singularized'][$plural] = $singular;
}
/**
* Singular English word to plural.
*
* @param string $word word to pluralize.
*
* @return string Plural noun.
*/
public function pluralize($word)
{
// Get the cached noun of it exists
if (isset($this->cache['pluralized'][$word]))
{
return $this->cache['pluralized'][$word];
}
// Check if the noun is already in plural form, i.e. in the singularized cache
if (isset($this->cache['singularized'][$word]))
{
return $word;
}
// Create the plural noun
if (in_array($word, $this->rules['uncountable']))
{
$_cache['pluralized'][$word] = $word;
return $word;
}
foreach ($this->rules['pluralization'] as $regexp => $replacement)
{
$matches = null;
$plural = preg_replace($regexp, $replacement, $word, -1, $matches);
if ($matches > 0)
{
$_cache['pluralized'][$word] = $plural;
return $plural;
}
}
return $word;
}
/**
* Plural English word to singular.
*
* @param string $word Word to singularize.
*
* @return string Singular noun.
*/
public function singularize($word)
{
// Get the cached noun of it exists
if (isset($this->cache['singularized'][$word]))
{
return $this->cache['singularized'][$word];
}
// Check if the noun is already in singular form, i.e. in the pluralized cache
if (isset($this->cache['pluralized'][$word]))
{
return $word;
}
// Create the singular noun
if (in_array($word, $this->rules['uncountable']))
{
$_cache['singularized'][$word] = $word;
return $word;
}
foreach ($this->rules['singularization'] as $regexp => $replacement)
{
$matches = null;
$singular = preg_replace($regexp, $replacement, $word, -1, $matches);
if ($matches > 0)
{
$_cache['singularized'][$word] = $singular;
return $singular;
}
}
return $word;
}
/**
* Returns given word as CamelCased.
*
* Converts a word like "foo_bar" or "foo bar" to "FooBar". It
* will remove non alphanumeric characters from the word, so
* "who's online" will be converted to "WhoSOnline"
*
* @param string $word Word to convert to camel case.
*
* @return string UpperCamelCasedWord
*/
public function camelize($word)
{
$word = preg_replace('/[^a-zA-Z0-9\s]/', ' ', $word);
$word = str_replace(' ', '', ucwords(strtolower(str_replace('_', ' ', $word))));
return $word;
}
/**
* Converts a word "into_it_s_underscored_version"
*
* Convert any "CamelCased" or "ordinary Word" into an "underscored_word".
*
* @param string $word Word to underscore
*
* @return string Underscored word
*/
public function underscore($word)
{
$word = preg_replace('/(\s)+/', '_', $word);
$word = strtolower(preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $word));
return $word;
}
/**
* Convert any "CamelCased" word into an array of strings
*
* Returns an array of strings each of which is a substring of string formed
* by splitting it at the camelcased letters.
*
* @param string $word Word to explode
*
* @return array Array of strings
*/
public function explode($word)
{
$result = explode('_', self::underscore($word));
return $result;
}
/**
* Convert an array of strings into a "CamelCased" word.
*
* @param array $words Array to implode
*
* @return string UpperCamelCasedWord
*/
public function implode($words)
{
$result = self::camelize(implode('_', $words));
return $result;
}
/**
* Returns a human-readable string from $word.
*
* Returns a human-readable string from $word, by replacing
* underscores with a space, and by upper-casing the initial
* character by default.
*
* @param string $word String to "humanize"
*
* @return string Human-readable word
*/
public function humanize($word)
{
$result = ucwords(strtolower(str_replace("_", " ", $word)));
return $result;
}
/**
* Returns camelBacked version of a string. Same as camelize but first char is lowercased.
*
* @param string $string String to be camelBacked.
*
* @return string
*
* @see camelize
*/
public function variablize($string)
{
$string = self::camelize(self::underscore($string));
$result = strtolower(substr($string, 0, 1));
$variable = preg_replace('/\\w/', $result, $string, 1);
return $variable;
}
/**
* Check to see if an English word is singular
*
* @param string $string The word to check
*
* @return boolean
*/
public function isSingular($string)
{
// Check cache assuming the string is plural.
$singular = $this->cache['singularized'][$string] ?? null;
$plural = $singular && isset($this->cache['pluralized'][$singular]) ? $this->cache['pluralized'][$singular] : null;
if ($singular && $plural)
{
return $plural != $string;
}
// If string is not in the cache, try to pluralize and singularize it.
return self::singularize(self::pluralize($string)) == $string;
}
/**
* Check to see if an English word is plural.
*
* @param string $string String to be checked.
*
* @return boolean
*/
public function isPlural($string)
{
// Uncountable objects are always singular (e.g. information)
if (in_array($string, $this->rules['uncountable']))
{
return false;
}
// Check cache assuming the string is singular.
$plural = $this->cache['pluralized'][$string] ?? null;
$singular = $plural && isset($this->cache['singularized'][$plural]) ? $this->cache['singularized'][$plural] : null;
if ($plural && $singular)
{
return $singular != $string;
}
// If string is not in the cache, try to singularize and pluralize it.
return self::pluralize(self::singularize($string)) == $string;
}
/**
* Gets a part of a CamelCased word by index.
*
* Use a negative index to start at the last part of the word (-1 is the
* last part)
*
* @param string $string Word
* @param integer $index Index of the part
* @param string $default Default value
*
* @return string
*/
public function getPart($string, $index, $default = null)
{
$parts = self::explode($string);
if ($index < 0)
{
$index = count($parts) + $index;
}
return $parts[$index] ?? $default;
}
}
PK �%"]�.��� � Encrypt/EncryptService.phpnu &1i� <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 2, or later
*/
namespace FOF30\Encrypt;
defined('_JEXEC') || die;
use FOF30\Container\Container;
use FOF30\Utils\Phpfunc;
/**
* Data encryption service for FOF-based components.
*
* This service allows you to transparently encrypt and decrypt *text* plaintext data. Use it to provide encryption for
* sensitive or personal data stored in your database. Please remember:
*
* - The default behavior is to create a file with a random key on your component's root. If the file cannot be created
* the encryption is turned off.
* - The key file is only created when you access the service. If you never use this service nothing happens (for
* backwards compatibility).
* - You have to manually encrypt and decrypt data. It won't happen magically.
* - Encrypted data cannot be searched unless you implement your own, slow, search algorithm.
* - Data encryption is meant to be used on top of, not instead of, any other security measures for your site.
* - Data encryption only protects against exploits targeting the database. If the attacker *also* gains read access to
* your filesystem OR if the attacker gains read / write access to the filesystem the encryption won't protect you.
* This is a full compromise of your site. At this point you're pwned and nothing can protect you. If you don't
* understand this simple truth do NOT use encryption.
* - This is meant as a simple and basic encryption layer. It has not been independently verified. Use at your own risk.
*
* This service has the following FOF application configuration parameters which can be declared under the "container"
* key (e.g. the "name" attribute of the fof.xml elements under fof > common > container > option):
*
* - encrypt_key_file The path to the key file, relative to the component's backend root and WITHOUT the .php extension
* - encrypt_key_const The constant for the key. By default it is COMPONENTNAME_FOF_ENCRYPT_SERVICE_SECRETKEY where
* COMPONENTNAME corresponds to the uppercase com_componentname without the com_ prefix.
*
* @package FOF30\Encrypt
*
* @since 3.3.2
*/
class EncryptService
{
/**
* The component's container
*
* @var Container
* @since 3.3.2
*/
private $container;
/**
* The encryption engine used by this service
*
* @var Aes
* @since 3.3.2
*/
private $aes;
/**
* EncryptService constructor.
*
* @param Container $c The FOF component container
*
* @since 3.3.2
*/
public function __construct(Container $c)
{
$this->container = $c;
$this->initialize();
}
/**
* Encrypt the plaintext $data and return the ciphertext prefixed by ###AES128###
*
* @param string $data The plaintext data
*
* @return string The ciphertext, prefixed by ###AES128###
*
* @since 3.3.2
*/
public function encrypt($data)
{
if (!is_object($this->aes))
{
return $data;
}
$encrypted = $this->aes->encryptString($data, true);
return '###AES128###' . $encrypted;
}
/**
* Decrypt the ciphertext, prefixed by ###AES128###, and return the plaintext.
*
* @param string $data The ciphertext, prefixed by ###AES128###
*
* @return string The plaintext data
*
* @since 3.3.2
*/
public function decrypt($data)
{
if (substr($data, 0, 12) != '###AES128###')
{
return $data;
}
$data = substr($data, 12);
if (!is_object($this->aes))
{
return $data;
}
$decrypted = $this->aes->decryptString($data, true);
// Decrypted data is null byte padded. We have to remove the padding before proceeding.
return rtrim($decrypted, "\0");
}
/**
* Initialize the AES cryptography object
*
* @return void
* @since 3.3.2
*
*/
private function initialize()
{
if (is_object($this->aes))
{
return;
}
$password = $this->getPassword();
if (empty($password))
{
return;
}
$phpFunc = new Phpfunc();
$this->aes = new Aes($password, 128, 'cbc', $phpFunc);
}
/**
* Returns the path to the secret key file
*
* @return string
*
* @since 3.3.2
*/
private function getPasswordFilePath()
{
$default = 'encrypt_service_key';
$baseName = $this->container->appConfig->get('container.encrypt_key_file', $default);
$baseName = trim($baseName, '/\\');
return $this->container->backEndPath . '/' . $baseName . '.php';
}
/**
* Get the name of the constant where the secret key is stored. Remember that this is searched first, before a new
* key file is created. You can define this constant anywhere in your code loaded before the encryption service is
* first used to prevent a key file being created.
*
* @return string
*
* @since 3.3.2
*/
private function getConstantName()
{
$default = strtoupper($this->container->bareComponentName) . '_FOF_ENCRYPT_SERVICE_SECRETKEY';
return $this->container->appConfig->get('container.encrypt_key_const', $default);
}
/**
* Returns the password used to encrypt information
*
* @return string
*
* @since 3.3.2
*/
private function getPassword()
{
$constantName = $this->getConstantName();
// If we have already read the file just return the key
if (defined($constantName))
{
return constant($constantName);
}
// Do I have a secret key file?
$filePath = $this->getPasswordFilePath();
// I can't get the path to the file. Cut our losses and assume we can get no key.
if (empty($filePath))
{
define($constantName, '');
return '';
}
// If not, try to create one.
if (!file_exists($filePath))
{
$this->makePasswordFile();
}
// We failed to create a new file? Cut our losses and assume we can get no key.
if (!file_exists($filePath) || !is_readable($filePath))
{
define($constantName, '');
return '';
}
// Try to include the key file
include_once $filePath;
// The key file contains garbage. Treason! Cut our losses and assume we can get no key.
if (!defined($constantName))
{
define($constantName, '');
return '';
}
// Finally, return the key which was defined in the file (happy path).
return constant($constantName);
}
/**
* Create a new secret key file using a long, randomly generated password. The password generator uses a crypto-safe
* pseudorandom number generator (PRNG) to ensure suitability of the password for encrypting data at rest.
*
* @return void
*
* @since 3.3.2
*/
private function makePasswordFile()
{
// Get the path to the new secret key file.
$filePath = $this->getPasswordFilePath();
// I can't get the path to the file. Sorry.
if (empty($filePath))
{
return;
}
$phpFunc = new Phpfunc();
$randval = new Randval($phpFunc);
$secretKey = $randval->getRandomPassword(64);
$constantName = $this->getConstantName();
$fileContent = "<?" . 'ph' . "p\n\n";
$fileContent .= <<< END
/**
* This file is automatically generated. It contains a secret key used for encrypting data by the component. Please do
* not remove, edit or manually replace this file. It will render your existing encrypted data unreadable forever.
*/
define('$constantName', '$secretKey');
END;
$this->container->filesystem->fileWrite($filePath, $fileContent);
}
}
PK �%"]���� � Encrypt/Randval.phpnu &1i� <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 2, or later
*/
namespace FOF30\Encrypt;
defined('_JEXEC') || die;
use FOF30\Utils\Phpfunc;
/**
* Generates cryptographically-secure random values.
*/
class Randval implements RandvalInterface
{
/**
* @var Phpfunc
*/
protected $phpfunc;
/**
*
* Constructor.
*
* @param Phpfunc $phpfunc An object to intercept PHP function calls;
* this makes testing easier.
*
*/
public function __construct(Phpfunc $phpfunc = null)
{
if (!is_object($phpfunc) || !($phpfunc instanceof Phpfunc))
{
$phpfunc = new Phpfunc();
}
$this->phpfunc = $phpfunc;
}
/**
*
* Returns a cryptographically secure random value.
*
* @param integer $bytes How many bytes to return
*
* @return string
*/
public function generate($bytes = 32)
{
if ($this->phpfunc->extension_loaded('openssl') && (version_compare(PHP_VERSION, '5.3.4') >= 0 || IS_WIN))
{
$strong = false;
$randBytes = openssl_random_pseudo_bytes($bytes, $strong);
if ($strong)
{
return $randBytes;
}
}
return $this->genRandomBytes($bytes);
}
/**
* Generate random bytes. Adapted from Joomla! 3.2.
*
* @param integer $length Length of the random data to generate
*
* @return string Random binary data
*/
public function genRandomBytes($length = 32)
{
$length = (int) $length;
$sslStr = '';
/*
* Collect any entropy available in the system along with a number
* of time measurements of operating system randomness.
*/
$bitsPerRound = 2;
$maxTimeMicro = 400;
$shaHashLength = 20;
$randomStr = '';
$total = $length;
// Check if we can use /dev/urandom.
$urandom = false;
$handle = null;
// This is PHP 5.3.3 and up
if ($this->phpfunc->function_exists('stream_set_read_buffer') && @is_readable('/dev/urandom'))
{
$handle = @fopen('/dev/urandom', 'rb');
if ($handle)
{
$urandom = true;
}
}
while ($length > strlen($randomStr))
{
$bytes = ($total > $shaHashLength) ? $shaHashLength : $total;
$total -= $bytes;
/*
* Collect any entropy available from the PHP system and filesystem.
* If we have ssl data that isn't strong, we use it once.
*/
$entropy = random_int(0, mt_getrandmax()) . uniqid(random_int(0, mt_getrandmax()), true) . $sslStr;
$entropy .= implode('', @fstat(fopen(__FILE__, 'r')));
$entropy .= memory_get_usage();
$sslStr = '';
if ($urandom)
{
stream_set_read_buffer($handle, 0);
$entropy .= @fread($handle, $bytes);
}
else
{
/*
* There is no external source of entropy so we repeat calls
* to mt_rand until we are assured there's real randomness in
* the result.
*
* Measure the time that the operations will take on average.
*/
$samples = 3;
$duration = 0;
for ($pass = 0; $pass < $samples; ++$pass)
{
$microStart = microtime(true) * 1000000;
$hash = sha1(random_int(0, mt_getrandmax()), true);
for ($count = 0; $count < 50; ++$count)
{
$hash = sha1($hash, true);
}
$microEnd = microtime(true) * 1000000;
$entropy .= $microStart . $microEnd;
if ($microStart >= $microEnd)
{
$microEnd += 1000000;
}
$duration += $microEnd - $microStart;
}
$duration = $duration / $samples;
/*
* Based on the average time, determine the total rounds so that
* the total running time is bounded to a reasonable number.
*/
$rounds = (int) (($maxTimeMicro / $duration) * 50);
/*
* Take additional measurements. On average we can expect
* at least $bitsPerRound bits of entropy from each measurement.
*/
$iter = $bytes * (int) ceil(8 / $bitsPerRound);
for ($pass = 0; $pass < $iter; ++$pass)
{
$microStart = microtime(true);
$hash = sha1(random_int(0, mt_getrandmax()), true);
for ($count = 0; $count < $rounds; ++$count)
{
$hash = sha1($hash, true);
}
$entropy .= $microStart . microtime(true);
}
}
$randomStr .= sha1($entropy, true);
}
if ($urandom)
{
@fclose($handle);
}
return substr($randomStr, 0, $length);
}
/**
* Return a randomly generated password using safe characters (a-z, A-Z, 0-9).
*
* @param int $length How many characters long should the password be. Default is 64.
*
* @return string
*
* @since 3.3.2
*/
public function getRandomPassword($length = 64)
{
$salt = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
$base = strlen($salt);
$makepass = '';
/*
* Start with a cryptographic strength random string, then convert it to
* a string with the numeric base of the salt.
* Shift the base conversion on each character so the character
* distribution is even, and randomize the start shift so it's not
* predictable.
*/
$random = $this->generate($length + 1);
$shift = ord($random[0]);
for ($i = 1; $i <= $length; ++$i)
{
$makepass .= $salt[($shift + ord($random[$i])) % $base];
$shift += ord($random[$i]);
}
return $makepass;
}
}
PK �%"]g�Xy y Encrypt/RandvalInterface.phpnu &1i� <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 2, or later
*/
namespace FOF30\Encrypt;
defined('_JEXEC') || die;
interface RandvalInterface
{
/**
*
* Returns a cryptographically secure random value.
*
* @return string
*
*/
public function generate();
}
PK �%"]w��* * Encrypt/Totp.phpnu &1i� <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 2, or later
*/
namespace FOF30\Encrypt;
defined('_JEXEC') || die;
class Totp
{
/**
* @var int The length of the resulting passcode (default: 6 digits)
*/
private $passCodeLength = 6;
/**
* @var number The PIN modulo. It is set automatically to log10(passCodeLength)
*/
private $pinModulo;
/**
* The length of the secret key, in characters (default: 10)
*
* @var int
*/
private $secretLength = 10;
/**
* The time step between successive TOTPs in seconds (default: 30 seconds)
*
* @var int
*/
private $timeStep = 30;
/**
* The Base32 encoder class
*
* @var Base32|null
*/
private $base32 = null;
/**
* Initialises an RFC6238-compatible TOTP generator. Please note that this
* class does not implement the constraint in the last paragraph of §5.2
* of RFC6238. It's up to you to ensure that the same user/device does not
* retry validation within the same Time Step.
*
* @param int $timeStep The Time Step (in seconds). Use 30 to be compatible with Google Authenticator.
* @param int $passCodeLength The generated passcode length. Default: 6 digits.
* @param int $secretLength The length of the secret key. Default: 10 bytes (80 bits).
* @param Base32 $base32 The base32 en/decrypter
*/
public function __construct($timeStep = 30, $passCodeLength = 6, $secretLength = 10, Base32 $base32 = null)
{
$this->timeStep = $timeStep;
$this->passCodeLength = $passCodeLength;
$this->secretLength = $secretLength;
$this->pinModulo = 10 ** $this->passCodeLength;
if (is_null($base32))
{
$this->base32 = new Base32();
}
else
{
$this->base32 = $base32;
}
}
/**
* Get the time period based on the $time timestamp and the Time Step
* defined. If $time is skipped or set to null the current timestamp will
* be used.
*
* @param int|null $time Timestamp
*
* @return int The time period since the UNIX Epoch
*/
public function getPeriod($time = null)
{
if (is_null($time))
{
$time = time();
}
$period = floor($time / $this->timeStep);
return $period;
}
/**
* Check is the given passcode $code is a valid TOTP generated using secret
* key $secret
*
* @param string $secret The Base32-encoded secret key
* @param string $code The passcode to check
* @param int $time The time to check it against. Leave null to check for the current server time.
*
* @return boolean True if the code is valid
*/
public function checkCode($secret, $code, $time = null)
{
$time = $this->getPeriod($time);
for ($i = -1; $i <= 1; $i++)
{
if ($this->getCode($secret, ($time + $i) * $this->timeStep) == $code)
{
return true;
}
}
return false;
}
/**
* Gets the TOTP passcode for a given secret key $secret and a given UNIX
* timestamp $time
*
* @param string $secret The Base32-encoded secret key
* @param int $time UNIX timestamp
*
* @return string
*/
public function getCode($secret, $time = null)
{
$period = $this->getPeriod($time);
$secret = $this->base32->decode($secret);
$time = pack("N", $period);
$time = str_pad($time, 8, chr(0), STR_PAD_LEFT);
$hash = hash_hmac('sha1', $time, $secret, true);
$offset = ord(substr($hash, -1));
$offset = $offset & 0xF;
$truncatedHash = $this->hashToInt($hash, $offset) & 0x7FFFFFFF;
$pinValue = str_pad($truncatedHash % $this->pinModulo, $this->passCodeLength, "0", STR_PAD_LEFT);
return $pinValue;
}
/**
* Returns a QR code URL for easy setup of TOTP apps like Google Authenticator
*
* @param string $user User
* @param string $hostname Hostname
* @param string $secret Secret string
*
* @return string
*/
public function getUrl($user, $hostname, $secret)
{
$url = sprintf("otpauth://totp/%s@%s?secret=%s", $user, $hostname, $secret);
$encoder = "https://chart.googleapis.com/chart?chs=200x200&chld=Q|2&cht=qr&chl=";
$encoderURL = $encoder . urlencode($url);
return $encoderURL;
}
/**
* Generates a (semi-)random Secret Key for TOTP generation
*
* @return string
*/
public function generateSecret()
{
$secret = "";
for ($i = 1; $i <= $this->secretLength; $i++)
{
$c = random_int(0, 255);
$secret .= pack("c", $c);
}
return $this->base32->encode($secret);
}
/**
* Extracts a part of a hash as an integer
*
* @param string $bytes The hash
* @param string $start The char to start from (0 = first char)
*
* @return string
*/
protected function hashToInt($bytes, $start)
{
$input = substr($bytes, $start, strlen($bytes) - $start);
$val2 = unpack("N", substr($input, 0, 4));
return $val2[1];
}
}
PK �%"]�W�
Encrypt/Base32.phpnu &1i� <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 2, or later
*/
namespace FOF30\Encrypt;
defined('_JEXEC') || die;
use InvalidArgumentException;
/**
* Base32 encoding class, used by the TOTP
*/
class Base32
{
/**
* CSRFC3548
*
* The character set as defined by RFC3548
* @link http://www.ietf.org/rfc/rfc3548.txt
*/
public const CSRFC3548 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567';
/**
* Convert any string to a base32 string
* This should be binary safe...
*
* @param string $str The string to convert
*
* @return string The converted base32 string
*/
public function encode($str)
{
return $this->fromBin($this->str2bin($str));
}
/**
* Convert any base32 string to a normal sctring
* This should be binary safe...
*
* @param string $str The base32 string to convert
*
* @return string The normal string
*/
public function decode($str)
{
$str = strtoupper($str);
return $this->bin2str($this->tobin($str));
}
/**
* Converts any ascii string to a binary string
*
* @param string $str The string you want to convert
*
* @return string String of 0's and 1's
*/
private function str2bin($str)
{
$chrs = unpack('C*', $str);
return vsprintf(str_repeat('%08b', count($chrs)), $chrs);
}
/**
* Converts a binary string to an ascii string
*
* @param string $str The string of 0's and 1's you want to convert
*
* @return string The ascii output
*
* @throws InvalidArgumentException
*/
private function bin2str($str)
{
if (strlen($str) % 8 > 0)
{
throw new InvalidArgumentException('Length must be divisible by 8');
}
if (!preg_match('/^[01]+$/', $str))
{
throw new InvalidArgumentException('Only 0\'s and 1\'s are permitted');
}
preg_match_all('/.{8}/', $str, $chrs);
$chrs = array_map('bindec', $chrs[0]);
// I'm just being slack here
array_unshift($chrs, 'C*');
return call_user_func_array('pack', $chrs);
}
/**
* Converts a correct binary string to base32
*
* @param string $str The string of 0's and 1's you want to convert
*
* @return string String encoded as base32
*
* @throws InvalidArgumentException
*/
private function fromBin($str)
{
if (strlen($str) % 8 > 0)
{
throw new InvalidArgumentException('Length must be divisible by 8');
}
if (!preg_match('/^[01]+$/', $str))
{
throw new InvalidArgumentException('Only 0\'s and 1\'s are permitted');
}
// Base32 works on the first 5 bits of a byte, so we insert blanks to pad it out
$str = preg_replace('/(.{5})/', '000$1', $str);
// We need a string divisible by 5
$length = strlen($str);
$rbits = $length & 7;
if ($rbits > 0)
{
// Excessive bits need to be padded
$ebits = substr($str, $length - $rbits);
$str = substr($str, 0, $length - $rbits);
$str .= "000$ebits" . str_repeat('0', 5 - strlen($ebits));
}
preg_match_all('/.{8}/', $str, $chrs);
$chrs = array_map([$this, 'mapCharset'], $chrs[0]);
return implode('', $chrs);
}
/**
* Accepts a base32 string and returns an ascii binary string
*
* @param string $str The base32 string to convert
*
* @return string Ascii binary string
*
* @throws InvalidArgumentException
*/
private function toBin($str)
{
if (!preg_match('/^[' . self::CSRFC3548 . ']+$/', $str))
{
throw new InvalidArgumentException('Base64 string must match character set');
}
// Convert the base32 string back to a binary string
$str = implode('', array_map([$this, 'mapBin'], str_split($str)));
// Remove the extra 0's we added
$str = preg_replace('/000(.{5})/', '$1', $str);
// Remove padding if necessary
$length = strlen($str);
$rbits = $length & 7;
if ($rbits > 0)
{
$str = substr($str, 0, $length - $rbits);
}
return $str;
}
/**
* Used with array_map to map the bits from a binary string
* directly into a base32 character set
*
* @param string $str The string of 0's and 1's you want to convert
*
* @return string Resulting base32 character
*
* @access private
*/
private function mapCharset($str)
{
// Huh!
$x = self::CSRFC3548;
return $x[bindec($str)];
}
/**
* Used with array_map to map the characters from a base32
* character set directly into a binary string
*
* @param string $chr The character to map
*
* @return string String of 0's and 1's
*
* @access private
*/
private function mapBin($chr)
{
return sprintf('%08b', strpos(self::CSRFC3548, $chr));
}
}
PK �%"]�#0�� � Encrypt/Aes.phpnu &1i� <?php
/**
* @package FOF
* @copyright Copyright (c)2010-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 2, or later
*/
namespace FOF30\Encrypt;
defined('_JEXEC') || die;
use FOF30\Encrypt\AesAdapter\AdapterInterface;
use FOF30\Encrypt\AesAdapter\OpenSSL;
use FOF30\Utils\Phpfunc;
/**
* A simple abstraction to AES encryption
*
* Usage:
*
* // Create a new instance. The key is ignored – only use it if you have legacy encrypted content you need to decrypt
* $aes = new Aes('ignored');
* // Set the password. Do not use uf you have legacy encrypted content you need to decrypt
* $aes->setPassword('yourRealPassword');
* // Encrypt something.
* $cipherText = $aes->encryptString($sourcePlainText);
* // Decrypt something
* $plainText = $aes->decryptString($sourceCipherText);
*/
class Aes
{
/**
* The cipher key.
*
* @var string
*/
private $key = '';
/**
* The AES encryption adapter in use.
*
* @var AdapterInterface
*/
private $adapter;
/**
* Initialise the AES encryption object.
*
* Note: If the key is not 16 bytes this class will do a stupid key expansion for legacy reasons (produce the
* SHA-256 of the key string and throw away half of it).
*
* @param string $key The encryption key (password). It can be a raw key (16 bytes) or a passphrase.
* @param int $strength Bit strength (128, 192 or 256) – ALWAYS USE 128 BITS. THIS PARAMETER IS DEPRECATED.
* @param string $mode Encryption mode. Can be ebc or cbc. We recommend using cbc.
* @param Phpfunc $phpfunc For testing
*/
public function __construct($key, $strength = 128, $mode = 'cbc', Phpfunc $phpfunc = null)
{
$this->adapter = new OpenSSL();
if (!$this->adapter->isSupported($phpfunc))
{
throw new \RuntimeException('Your server does not have the PHP OpenSSL extension enabled. This is required for encryption handling.');
}
$this->adapter->setEncryptionMode($mode, $strength);
$this->setPassword($key, true);
}
/**
* Is AES encryption supported by this PHP installation?
*
* @return boolean
*/
public static function isSupported(Phpfunc $phpfunc = null)
{
if (!is_object($phpfunc) || !($phpfunc instanceof $phpfunc))
{
$phpfunc = new Phpfunc();
}
$adapter = new OpenSSL();
if (!$adapter->isSupported($phpfunc))
{
return false;
}
if (!$phpfunc->function_exists('base64_encode'))
{
return false;
}
if (!$phpfunc->function_exists('base64_decode'))
{
return false;
}
if (!$phpfunc->function_exists('hash_algos'))
{
return false;
}
$algorightms = $phpfunc->hash_algos();
if (!in_array('sha256', $algorightms))
{
return false;
}
return true;
}
/**
* Sets the password for this instance.
*
* WARNING: Do not use the legacy mode, it's insecure
*
* @param string $password The password (either user-provided password or binary encryption key) to use
* @param bool $legacyMode True to use the legacy key expansion. We recommend against using it.
*/
public function setPassword($password, $legacyMode = false)
{
$this->key = $password;
$passLength = strlen($password);
if (function_exists('mb_strlen'))
{
$passLength = mb_strlen($password, 'ASCII');
}
// Legacy mode was doing something stupid, requiring a key of 32 bytes. DO NOT USE LEGACY MODE!
if ($legacyMode && ($passLength != 32))
{
// Legacy mode: use the sha256 of the password
$this->key = hash('sha256', $password, true);
// We have to trim or zero pad the password (we end up throwing half of it away in Rijndael-128 / AES...)
$this->key = $this->adapter->resizeKey($this->key, $this->adapter->getBlockSize());
}
}
/**
* Encrypts a string using AES
*
* @param string $stringToEncrypt The plaintext to encrypt
* @param bool $base64encoded Should I Base64-encode the result?
*
* @return string The cryptotext. Please note that the first 16 bytes of
* the raw string is the IV (initialisation vector) which
* is necessary for decoding the string.
*/
public function encryptString($stringToEncrypt, $base64encoded = true)
{
$blockSize = $this->adapter->getBlockSize();
$randVal = new Randval();
$iv = $randVal->generate($blockSize);
$key = $this->getExpandedKey($blockSize, $iv);
$cipherText = $this->adapter->encrypt($stringToEncrypt, $key, $iv);
// Optionally pass the result through Base64 encoding
if ($base64encoded)
{
$cipherText = base64_encode($cipherText);
}
// Return the result
return $cipherText;
}
/**
* Decrypts a ciphertext into a plaintext string using AES
*
* @param string $stringToDecrypt The ciphertext to decrypt. The first 16 bytes of the raw string must contain
* the IV (initialisation vector).
* @param bool $base64encoded Should I Base64-decode the data before decryption?
*
* @return string The plain text string
*/
public function decryptString($stringToDecrypt, $base64encoded = true)
{
if ($base64encoded)
{
$stringToDecrypt = base64_decode($stringToDecrypt);
}
// Extract IV
$iv_size = $this->adapter->getBlockSize();
$iv = substr($stringToDecrypt, 0, $iv_size);
$key = $this->getExpandedKey($iv_size, $iv);
// Decrypt the data
$plainText = $this->adapter->decrypt($stringToDecrypt, $key);
return $plainText;
}
/**
* @param $blockSize
* @param $iv
*
* @return string
*/
public function getExpandedKey($blockSize, $iv)
{
$key = $this->key;
$passLength = strlen($key);
if (function_exists('mb_strlen'))
{
$passLength = mb_strlen($key, 'ASCII');
}
if ($passLength != $blockSize)
{
$iterations = 1000;
$salt = $this->adapter->resizeKey($iv, 16);
$key = hash_pbkdf2('sha256', $this->key, $salt, $iterations, $blockSize, true);
}
return $key;
}
}
if (!function_exists('hash_pbkdf2'))
{
function hash_pbkdf2($algo, $password, $salt, $count, $length = 0, $raw_output = false)
{
if (!in_array(strtolower($algo), hash_algos()))
{
trigger_error(__FUNCTION__ . '(): Unknown hashing algorithm: ' . $algo, E_USER_WARNING);
}
if (!is_numeric($count))
{
trigger_error(__FUNCTION__ . '(): expects parameter 4 to be long, ' . gettype($count) . ' given', E_USER_WARNING);
}
if (!is_numeric($length))
{
trigger_error(__FUNCTION__ . '(): expects parameter 5 to be long, ' . gettype($length) . ' given', E_USER_WARNING);
}
if ($count <= 0)
{
trigger_error(__FUNCTION__ . '(): Iterations must be a positive integer: ' . $count, E_USER_WARNING);
}
if ($length < 0)
{
trigger_error(__FUNCTION__ . '(): Length must be greater than or equal to 0: ' . $length, E_USER_WARNING);
}
$output = '';
$block_count = $length ? ceil($length / strlen(hash($algo, '', $raw_output))) : 1;
for ($i = 1; $i <= $block_count; $i++)
{
$last = $xorsum = hash_hmac($algo, $salt . pack('N', $i), $password, true);
for ($j = 1; $j < $count; $j++)
{
$xorsum ^= ($last = hash_hmac($algo, $last, $password, true));
}
$output .= $xorsum;
}
if (!$raw_output)
{
$output = bin2hex($output);
}
return $length ? substr($output, 0, $length) : $output;
}
}
PK �%"]�v��
'