Update website
This commit is contained in:
parent
4413528994
commit
1d90fbf296
6865 changed files with 1091082 additions and 0 deletions
7
admin/phpMyAdmin/vendor/autoload.php
vendored
Normal file
7
admin/phpMyAdmin/vendor/autoload.php
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
<?php
|
||||
|
||||
// autoload.php @generated by Composer
|
||||
|
||||
require_once __DIR__ . '/composer/autoload_real.php';
|
||||
|
||||
return ComposerAutoloaderInit5a360facea79a6ba3440ba7eaed9051a::getLoader();
|
22
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/LICENSE
vendored
Normal file
22
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/LICENSE
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2017, Ben Scholzen 'DASPRiD'
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
39
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/README.md
vendored
Normal file
39
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/README.md
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
# QR Code generator
|
||||
|
||||
[](https://github.com/Bacon/BaconQrCode/actions/workflows/ci.yml)
|
||||
[](https://codecov.io/gh/Bacon/BaconQrCode)
|
||||
[](https://packagist.org/packages/bacon/bacon-qr-code)
|
||||
[](https://packagist.org/packages/bacon/bacon-qr-code)
|
||||
[](https://packagist.org/packages/bacon/bacon-qr-code)
|
||||
|
||||
|
||||
## Introduction
|
||||
BaconQrCode is a port of QR code portion of the ZXing library. It currently
|
||||
only features the encoder part, but could later receive the decoder part as
|
||||
well.
|
||||
|
||||
As the Reed Solomon codec implementation of the ZXing library performs quite
|
||||
slow in PHP, it was exchanged with the implementation by Phil Karn.
|
||||
|
||||
|
||||
## Example usage
|
||||
```php
|
||||
use BaconQrCode\Renderer\ImageRenderer;
|
||||
use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
|
||||
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
|
||||
use BaconQrCode\Writer;
|
||||
|
||||
$renderer = new ImageRenderer(
|
||||
new RendererStyle(400),
|
||||
new ImagickImageBackEnd()
|
||||
);
|
||||
$writer = new Writer($renderer);
|
||||
$writer->writeFile('Hello World!', 'qrcode.png');
|
||||
```
|
||||
|
||||
## Available image renderer back ends
|
||||
BaconQrCode comes with multiple back ends for rendering images. Currently included are the following:
|
||||
|
||||
- `ImagickImageBackEnd`: renders raster images using the Imagick library
|
||||
- `SvgImageBackEnd`: renders SVG files using XMLWriter
|
||||
- `EpsImageBackEnd`: renders EPS files
|
44
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/composer.json
vendored
Normal file
44
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/composer.json
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"name": "bacon/bacon-qr-code",
|
||||
"description": "BaconQrCode is a QR code generator for PHP.",
|
||||
"license" : "BSD-2-Clause",
|
||||
"homepage": "https://github.com/Bacon/BaconQrCode",
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0",
|
||||
"ext-iconv": "*",
|
||||
"dasprid/enum": "^1.0.3"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-imagick": "to generate QR code images"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ben Scholzen 'DASPRiD'",
|
||||
"email": "mail@dasprids.de",
|
||||
"homepage": "https://dasprids.de/",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"BaconQrCode\\": "src/"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7 | ^8 | ^9",
|
||||
"spatie/phpunit-snapshot-assertions": "^4.2.9",
|
||||
"squizlabs/php_codesniffer": "^3.4",
|
||||
"phly/keep-a-changelog": "^2.1"
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"ocramius/package-versions": true
|
||||
}
|
||||
},
|
||||
"archive": {
|
||||
"exclude": [
|
||||
"/test",
|
||||
"/phpunit.xml.dist"
|
||||
]
|
||||
}
|
||||
}
|
372
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/BitArray.php
vendored
Normal file
372
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/BitArray.php
vendored
Normal file
|
@ -0,0 +1,372 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
use SplFixedArray;
|
||||
|
||||
/**
|
||||
* A simple, fast array of bits.
|
||||
*/
|
||||
final class BitArray
|
||||
{
|
||||
/**
|
||||
* Bits represented as an array of integers.
|
||||
*
|
||||
* @var SplFixedArray<int>
|
||||
*/
|
||||
private $bits;
|
||||
|
||||
/**
|
||||
* Size of the bit array in bits.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $size;
|
||||
|
||||
/**
|
||||
* Creates a new bit array with a given size.
|
||||
*/
|
||||
public function __construct(int $size = 0)
|
||||
{
|
||||
$this->size = $size;
|
||||
$this->bits = SplFixedArray::fromArray(array_fill(0, ($this->size + 31) >> 3, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size in bits.
|
||||
*/
|
||||
public function getSize() : int
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the size in bytes.
|
||||
*/
|
||||
public function getSizeInBytes() : int
|
||||
{
|
||||
return ($this->size + 7) >> 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures that the array has a minimum capacity.
|
||||
*/
|
||||
public function ensureCapacity(int $size) : void
|
||||
{
|
||||
if ($size > count($this->bits) << 5) {
|
||||
$this->bits->setSize(($size + 31) >> 5);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a specific bit.
|
||||
*/
|
||||
public function get(int $i) : bool
|
||||
{
|
||||
return 0 !== ($this->bits[$i >> 5] & (1 << ($i & 0x1f)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a specific bit.
|
||||
*/
|
||||
public function set(int $i) : void
|
||||
{
|
||||
$this->bits[$i >> 5] = $this->bits[$i >> 5] | 1 << ($i & 0x1f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips a specific bit.
|
||||
*/
|
||||
public function flip(int $i) : void
|
||||
{
|
||||
$this->bits[$i >> 5] ^= 1 << ($i & 0x1f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next set bit position from a given position.
|
||||
*/
|
||||
public function getNextSet(int $from) : int
|
||||
{
|
||||
if ($from >= $this->size) {
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
$bitsOffset = $from >> 5;
|
||||
$currentBits = $this->bits[$bitsOffset];
|
||||
$bitsLength = count($this->bits);
|
||||
$currentBits &= ~((1 << ($from & 0x1f)) - 1);
|
||||
|
||||
while (0 === $currentBits) {
|
||||
if (++$bitsOffset === $bitsLength) {
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
$currentBits = $this->bits[$bitsOffset];
|
||||
}
|
||||
|
||||
$result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits);
|
||||
return $result > $this->size ? $this->size : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next unset bit position from a given position.
|
||||
*/
|
||||
public function getNextUnset(int $from) : int
|
||||
{
|
||||
if ($from >= $this->size) {
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
$bitsOffset = $from >> 5;
|
||||
$currentBits = ~$this->bits[$bitsOffset];
|
||||
$bitsLength = count($this->bits);
|
||||
$currentBits &= ~((1 << ($from & 0x1f)) - 1);
|
||||
|
||||
while (0 === $currentBits) {
|
||||
if (++$bitsOffset === $bitsLength) {
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
$currentBits = ~$this->bits[$bitsOffset];
|
||||
}
|
||||
|
||||
$result = ($bitsOffset << 5) + BitUtils::numberOfTrailingZeros($currentBits);
|
||||
return $result > $this->size ? $this->size : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a bulk of bits.
|
||||
*/
|
||||
public function setBulk(int $i, int $newBits) : void
|
||||
{
|
||||
$this->bits[$i >> 5] = $newBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a range of bits.
|
||||
*
|
||||
* @throws InvalidArgumentException if end is smaller than start
|
||||
*/
|
||||
public function setRange(int $start, int $end) : void
|
||||
{
|
||||
if ($end < $start) {
|
||||
throw new InvalidArgumentException('End must be greater or equal to start');
|
||||
}
|
||||
|
||||
if ($end === $start) {
|
||||
return;
|
||||
}
|
||||
|
||||
--$end;
|
||||
|
||||
$firstInt = $start >> 5;
|
||||
$lastInt = $end >> 5;
|
||||
|
||||
for ($i = $firstInt; $i <= $lastInt; ++$i) {
|
||||
$firstBit = $i > $firstInt ? 0 : $start & 0x1f;
|
||||
$lastBit = $i < $lastInt ? 31 : $end & 0x1f;
|
||||
|
||||
if (0 === $firstBit && 31 === $lastBit) {
|
||||
$mask = 0x7fffffff;
|
||||
} else {
|
||||
$mask = 0;
|
||||
|
||||
for ($j = $firstBit; $j < $lastBit; ++$j) {
|
||||
$mask |= 1 << $j;
|
||||
}
|
||||
}
|
||||
|
||||
$this->bits[$i] = $this->bits[$i] | $mask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the bit array, unsetting every bit.
|
||||
*/
|
||||
public function clear() : void
|
||||
{
|
||||
$bitsLength = count($this->bits);
|
||||
|
||||
for ($i = 0; $i < $bitsLength; ++$i) {
|
||||
$this->bits[$i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a range of bits is set or not set.
|
||||
|
||||
* @throws InvalidArgumentException if end is smaller than start
|
||||
*/
|
||||
public function isRange(int $start, int $end, bool $value) : bool
|
||||
{
|
||||
if ($end < $start) {
|
||||
throw new InvalidArgumentException('End must be greater or equal to start');
|
||||
}
|
||||
|
||||
if ($end === $start) {
|
||||
return true;
|
||||
}
|
||||
|
||||
--$end;
|
||||
|
||||
$firstInt = $start >> 5;
|
||||
$lastInt = $end >> 5;
|
||||
|
||||
for ($i = $firstInt; $i <= $lastInt; ++$i) {
|
||||
$firstBit = $i > $firstInt ? 0 : $start & 0x1f;
|
||||
$lastBit = $i < $lastInt ? 31 : $end & 0x1f;
|
||||
|
||||
if (0 === $firstBit && 31 === $lastBit) {
|
||||
$mask = 0x7fffffff;
|
||||
} else {
|
||||
$mask = 0;
|
||||
|
||||
for ($j = $firstBit; $j <= $lastBit; ++$j) {
|
||||
$mask |= 1 << $j;
|
||||
}
|
||||
}
|
||||
|
||||
if (($this->bits[$i] & $mask) !== ($value ? $mask : 0)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a bit to the array.
|
||||
*/
|
||||
public function appendBit(bool $bit) : void
|
||||
{
|
||||
$this->ensureCapacity($this->size + 1);
|
||||
|
||||
if ($bit) {
|
||||
$this->bits[$this->size >> 5] = $this->bits[$this->size >> 5] | (1 << ($this->size & 0x1f));
|
||||
}
|
||||
|
||||
++$this->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends a number of bits (up to 32) to the array.
|
||||
|
||||
* @throws InvalidArgumentException if num bits is not between 0 and 32
|
||||
*/
|
||||
public function appendBits(int $value, int $numBits) : void
|
||||
{
|
||||
if ($numBits < 0 || $numBits > 32) {
|
||||
throw new InvalidArgumentException('Num bits must be between 0 and 32');
|
||||
}
|
||||
|
||||
$this->ensureCapacity($this->size + $numBits);
|
||||
|
||||
for ($numBitsLeft = $numBits; $numBitsLeft > 0; $numBitsLeft--) {
|
||||
$this->appendBit((($value >> ($numBitsLeft - 1)) & 0x01) === 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends another bit array to this array.
|
||||
*/
|
||||
public function appendBitArray(self $other) : void
|
||||
{
|
||||
$otherSize = $other->getSize();
|
||||
$this->ensureCapacity($this->size + $other->getSize());
|
||||
|
||||
for ($i = 0; $i < $otherSize; ++$i) {
|
||||
$this->appendBit($other->get($i));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an exclusive-or comparision on the current bit array.
|
||||
*
|
||||
* @throws InvalidArgumentException if sizes don't match
|
||||
*/
|
||||
public function xorBits(self $other) : void
|
||||
{
|
||||
$bitsLength = count($this->bits);
|
||||
$otherBits = $other->getBitArray();
|
||||
|
||||
if ($bitsLength !== count($otherBits)) {
|
||||
throw new InvalidArgumentException('Sizes don\'t match');
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $bitsLength; ++$i) {
|
||||
$this->bits[$i] = $this->bits[$i] ^ $otherBits[$i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the bit array to a byte array.
|
||||
*
|
||||
* @return SplFixedArray<int>
|
||||
*/
|
||||
public function toBytes(int $bitOffset, int $numBytes) : SplFixedArray
|
||||
{
|
||||
$bytes = new SplFixedArray($numBytes);
|
||||
|
||||
for ($i = 0; $i < $numBytes; ++$i) {
|
||||
$byte = 0;
|
||||
|
||||
for ($j = 0; $j < 8; ++$j) {
|
||||
if ($this->get($bitOffset)) {
|
||||
$byte |= 1 << (7 - $j);
|
||||
}
|
||||
|
||||
++$bitOffset;
|
||||
}
|
||||
|
||||
$bytes[$i] = $byte;
|
||||
}
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the internal bit array.
|
||||
*
|
||||
* @return SplFixedArray<int>
|
||||
*/
|
||||
public function getBitArray() : SplFixedArray
|
||||
{
|
||||
return $this->bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the array.
|
||||
*/
|
||||
public function reverse() : void
|
||||
{
|
||||
$newBits = new SplFixedArray(count($this->bits));
|
||||
|
||||
for ($i = 0; $i < $this->size; ++$i) {
|
||||
if ($this->get($this->size - $i - 1)) {
|
||||
$newBits[$i >> 5] = $newBits[$i >> 5] | (1 << ($i & 0x1f));
|
||||
}
|
||||
}
|
||||
|
||||
$this->bits = $newBits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the bit array.
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
for ($i = 0; $i < $this->size; ++$i) {
|
||||
if (0 === ($i & 0x07)) {
|
||||
$result .= ' ';
|
||||
}
|
||||
|
||||
$result .= $this->get($i) ? 'X' : '.';
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
313
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/BitMatrix.php
vendored
Normal file
313
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/BitMatrix.php
vendored
Normal file
|
@ -0,0 +1,313 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
use SplFixedArray;
|
||||
|
||||
/**
|
||||
* Bit matrix.
|
||||
*
|
||||
* Represents a 2D matrix of bits. In function arguments below, and throughout
|
||||
* the common module, x is the column position, and y is the row position. The
|
||||
* ordering is always x, y. The origin is at the top-left.
|
||||
*/
|
||||
class BitMatrix
|
||||
{
|
||||
/**
|
||||
* Width of the bit matrix.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $width;
|
||||
|
||||
/**
|
||||
* Height of the bit matrix.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $height;
|
||||
|
||||
/**
|
||||
* Size in bits of each individual row.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $rowSize;
|
||||
|
||||
/**
|
||||
* Bits representation.
|
||||
*
|
||||
* @var SplFixedArray<int>
|
||||
*/
|
||||
private $bits;
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if a dimension is smaller than zero
|
||||
*/
|
||||
public function __construct(int $width, int $height = null)
|
||||
{
|
||||
if (null === $height) {
|
||||
$height = $width;
|
||||
}
|
||||
|
||||
if ($width < 1 || $height < 1) {
|
||||
throw new InvalidArgumentException('Both dimensions must be greater than zero');
|
||||
}
|
||||
|
||||
$this->width = $width;
|
||||
$this->height = $height;
|
||||
$this->rowSize = ($width + 31) >> 5;
|
||||
$this->bits = SplFixedArray::fromArray(array_fill(0, $this->rowSize * $height, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the requested bit, where true means black.
|
||||
*/
|
||||
public function get(int $x, int $y) : bool
|
||||
{
|
||||
$offset = $y * $this->rowSize + ($x >> 5);
|
||||
return 0 !== (BitUtils::unsignedRightShift($this->bits[$offset], ($x & 0x1f)) & 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given bit to true.
|
||||
*/
|
||||
public function set(int $x, int $y) : void
|
||||
{
|
||||
$offset = $y * $this->rowSize + ($x >> 5);
|
||||
$this->bits[$offset] = $this->bits[$offset] | (1 << ($x & 0x1f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips the given bit.
|
||||
*/
|
||||
public function flip(int $x, int $y) : void
|
||||
{
|
||||
$offset = $y * $this->rowSize + ($x >> 5);
|
||||
$this->bits[$offset] = $this->bits[$offset] ^ (1 << ($x & 0x1f));
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all bits (set to false).
|
||||
*/
|
||||
public function clear() : void
|
||||
{
|
||||
$max = count($this->bits);
|
||||
|
||||
for ($i = 0; $i < $max; ++$i) {
|
||||
$this->bits[$i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a square region of the bit matrix to true.
|
||||
*
|
||||
* @throws InvalidArgumentException if left or top are negative
|
||||
* @throws InvalidArgumentException if width or height are smaller than 1
|
||||
* @throws InvalidArgumentException if region does not fit into the matix
|
||||
*/
|
||||
public function setRegion(int $left, int $top, int $width, int $height) : void
|
||||
{
|
||||
if ($top < 0 || $left < 0) {
|
||||
throw new InvalidArgumentException('Left and top must be non-negative');
|
||||
}
|
||||
|
||||
if ($height < 1 || $width < 1) {
|
||||
throw new InvalidArgumentException('Width and height must be at least 1');
|
||||
}
|
||||
|
||||
$right = $left + $width;
|
||||
$bottom = $top + $height;
|
||||
|
||||
if ($bottom > $this->height || $right > $this->width) {
|
||||
throw new InvalidArgumentException('The region must fit inside the matrix');
|
||||
}
|
||||
|
||||
for ($y = $top; $y < $bottom; ++$y) {
|
||||
$offset = $y * $this->rowSize;
|
||||
|
||||
for ($x = $left; $x < $right; ++$x) {
|
||||
$index = $offset + ($x >> 5);
|
||||
$this->bits[$index] = $this->bits[$index] | (1 << ($x & 0x1f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A fast method to retrieve one row of data from the matrix as a BitArray.
|
||||
*/
|
||||
public function getRow(int $y, BitArray $row = null) : BitArray
|
||||
{
|
||||
if (null === $row || $row->getSize() < $this->width) {
|
||||
$row = new BitArray($this->width);
|
||||
}
|
||||
|
||||
$offset = $y * $this->rowSize;
|
||||
|
||||
for ($x = 0; $x < $this->rowSize; ++$x) {
|
||||
$row->setBulk($x << 5, $this->bits[$offset + $x]);
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a row of data from a BitArray.
|
||||
*/
|
||||
public function setRow(int $y, BitArray $row) : void
|
||||
{
|
||||
$bits = $row->getBitArray();
|
||||
|
||||
for ($i = 0; $i < $this->rowSize; ++$i) {
|
||||
$this->bits[$y * $this->rowSize + $i] = $bits[$i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is useful in detecting the enclosing rectangle of a 'pure' barcode.
|
||||
*
|
||||
* @return int[]|null
|
||||
*/
|
||||
public function getEnclosingRectangle() : ?array
|
||||
{
|
||||
$left = $this->width;
|
||||
$top = $this->height;
|
||||
$right = -1;
|
||||
$bottom = -1;
|
||||
|
||||
for ($y = 0; $y < $this->height; ++$y) {
|
||||
for ($x32 = 0; $x32 < $this->rowSize; ++$x32) {
|
||||
$bits = $this->bits[$y * $this->rowSize + $x32];
|
||||
|
||||
if (0 !== $bits) {
|
||||
if ($y < $top) {
|
||||
$top = $y;
|
||||
}
|
||||
|
||||
if ($y > $bottom) {
|
||||
$bottom = $y;
|
||||
}
|
||||
|
||||
if ($x32 * 32 < $left) {
|
||||
$bit = 0;
|
||||
|
||||
while (($bits << (31 - $bit)) === 0) {
|
||||
$bit++;
|
||||
}
|
||||
|
||||
if (($x32 * 32 + $bit) < $left) {
|
||||
$left = $x32 * 32 + $bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($x32 * 32 + 31 > $right) {
|
||||
$bit = 31;
|
||||
|
||||
while (0 === BitUtils::unsignedRightShift($bits, $bit)) {
|
||||
--$bit;
|
||||
}
|
||||
|
||||
if (($x32 * 32 + $bit) > $right) {
|
||||
$right = $x32 * 32 + $bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$width = $right - $left;
|
||||
$height = $bottom - $top;
|
||||
|
||||
if ($width < 0 || $height < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return [$left, $top, $width, $height];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the most top left set bit.
|
||||
*
|
||||
* This is useful in detecting a corner of a 'pure' barcode.
|
||||
*
|
||||
* @return int[]|null
|
||||
*/
|
||||
public function getTopLeftOnBit() : ?array
|
||||
{
|
||||
$bitsOffset = 0;
|
||||
|
||||
while ($bitsOffset < count($this->bits) && 0 === $this->bits[$bitsOffset]) {
|
||||
++$bitsOffset;
|
||||
}
|
||||
|
||||
if (count($this->bits) === $bitsOffset) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$x = intdiv($bitsOffset, $this->rowSize);
|
||||
$y = ($bitsOffset % $this->rowSize) << 5;
|
||||
|
||||
$bits = $this->bits[$bitsOffset];
|
||||
$bit = 0;
|
||||
|
||||
while (0 === ($bits << (31 - $bit))) {
|
||||
++$bit;
|
||||
}
|
||||
|
||||
$x += $bit;
|
||||
|
||||
return [$x, $y];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the most bottom right set bit.
|
||||
*
|
||||
* This is useful in detecting a corner of a 'pure' barcode.
|
||||
*
|
||||
* @return int[]|null
|
||||
*/
|
||||
public function getBottomRightOnBit() : ?array
|
||||
{
|
||||
$bitsOffset = count($this->bits) - 1;
|
||||
|
||||
while ($bitsOffset >= 0 && 0 === $this->bits[$bitsOffset]) {
|
||||
--$bitsOffset;
|
||||
}
|
||||
|
||||
if ($bitsOffset < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$x = intdiv($bitsOffset, $this->rowSize);
|
||||
$y = ($bitsOffset % $this->rowSize) << 5;
|
||||
|
||||
$bits = $this->bits[$bitsOffset];
|
||||
$bit = 0;
|
||||
|
||||
while (0 === BitUtils::unsignedRightShift($bits, $bit)) {
|
||||
--$bit;
|
||||
}
|
||||
|
||||
$x += $bit;
|
||||
|
||||
return [$x, $y];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of the matrix,
|
||||
*/
|
||||
public function getWidth() : int
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height of the matrix.
|
||||
*/
|
||||
public function getHeight() : int
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
}
|
41
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/BitUtils.php
vendored
Normal file
41
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/BitUtils.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
/**
|
||||
* General bit utilities.
|
||||
*
|
||||
* All utility methods are based on 32-bit integers and also work on 64-bit
|
||||
* systems.
|
||||
*/
|
||||
final class BitUtils
|
||||
{
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an unsigned right shift.
|
||||
*
|
||||
* This is the same as the unsigned right shift operator ">>>" in other
|
||||
* languages.
|
||||
*/
|
||||
public static function unsignedRightShift(int $a, int $b) : int
|
||||
{
|
||||
return (
|
||||
$a >= 0
|
||||
? $a >> $b
|
||||
: (($a & 0x7fffffff) >> $b) | (0x40000000 >> ($b - 1))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of trailing zeros.
|
||||
*/
|
||||
public static function numberOfTrailingZeros(int $i) : int
|
||||
{
|
||||
$lastPos = strrpos(str_pad(decbin($i), 32, '0', STR_PAD_LEFT), '1');
|
||||
return $lastPos === false ? 32 : 31 - $lastPos;
|
||||
}
|
||||
}
|
183
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/CharacterSetEci.php
vendored
Normal file
183
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/CharacterSetEci.php
vendored
Normal file
|
@ -0,0 +1,183 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
use DASPRiD\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1 of ISO 18004.
|
||||
*
|
||||
* @method static self CP437()
|
||||
* @method static self ISO8859_1()
|
||||
* @method static self ISO8859_2()
|
||||
* @method static self ISO8859_3()
|
||||
* @method static self ISO8859_4()
|
||||
* @method static self ISO8859_5()
|
||||
* @method static self ISO8859_6()
|
||||
* @method static self ISO8859_7()
|
||||
* @method static self ISO8859_8()
|
||||
* @method static self ISO8859_9()
|
||||
* @method static self ISO8859_10()
|
||||
* @method static self ISO8859_11()
|
||||
* @method static self ISO8859_12()
|
||||
* @method static self ISO8859_13()
|
||||
* @method static self ISO8859_14()
|
||||
* @method static self ISO8859_15()
|
||||
* @method static self ISO8859_16()
|
||||
* @method static self SJIS()
|
||||
* @method static self CP1250()
|
||||
* @method static self CP1251()
|
||||
* @method static self CP1252()
|
||||
* @method static self CP1256()
|
||||
* @method static self UNICODE_BIG_UNMARKED()
|
||||
* @method static self UTF8()
|
||||
* @method static self ASCII()
|
||||
* @method static self BIG5()
|
||||
* @method static self GB18030()
|
||||
* @method static self EUC_KR()
|
||||
*/
|
||||
final class CharacterSetEci extends AbstractEnum
|
||||
{
|
||||
protected const CP437 = [[0, 2]];
|
||||
protected const ISO8859_1 = [[1, 3], 'ISO-8859-1'];
|
||||
protected const ISO8859_2 = [[4], 'ISO-8859-2'];
|
||||
protected const ISO8859_3 = [[5], 'ISO-8859-3'];
|
||||
protected const ISO8859_4 = [[6], 'ISO-8859-4'];
|
||||
protected const ISO8859_5 = [[7], 'ISO-8859-5'];
|
||||
protected const ISO8859_6 = [[8], 'ISO-8859-6'];
|
||||
protected const ISO8859_7 = [[9], 'ISO-8859-7'];
|
||||
protected const ISO8859_8 = [[10], 'ISO-8859-8'];
|
||||
protected const ISO8859_9 = [[11], 'ISO-8859-9'];
|
||||
protected const ISO8859_10 = [[12], 'ISO-8859-10'];
|
||||
protected const ISO8859_11 = [[13], 'ISO-8859-11'];
|
||||
protected const ISO8859_12 = [[14], 'ISO-8859-12'];
|
||||
protected const ISO8859_13 = [[15], 'ISO-8859-13'];
|
||||
protected const ISO8859_14 = [[16], 'ISO-8859-14'];
|
||||
protected const ISO8859_15 = [[17], 'ISO-8859-15'];
|
||||
protected const ISO8859_16 = [[18], 'ISO-8859-16'];
|
||||
protected const SJIS = [[20], 'Shift_JIS'];
|
||||
protected const CP1250 = [[21], 'windows-1250'];
|
||||
protected const CP1251 = [[22], 'windows-1251'];
|
||||
protected const CP1252 = [[23], 'windows-1252'];
|
||||
protected const CP1256 = [[24], 'windows-1256'];
|
||||
protected const UNICODE_BIG_UNMARKED = [[25], 'UTF-16BE', 'UnicodeBig'];
|
||||
protected const UTF8 = [[26], 'UTF-8'];
|
||||
protected const ASCII = [[27, 170], 'US-ASCII'];
|
||||
protected const BIG5 = [[28]];
|
||||
protected const GB18030 = [[29], 'GB2312', 'EUC_CN', 'GBK'];
|
||||
protected const EUC_KR = [[30], 'EUC-KR'];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
private $values;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $otherEncodingNames;
|
||||
|
||||
/**
|
||||
* @var array<int, self>|null
|
||||
*/
|
||||
private static $valueToEci;
|
||||
|
||||
/**
|
||||
* @var array<string, self>|null
|
||||
*/
|
||||
private static $nameToEci;
|
||||
|
||||
/**
|
||||
* @param int[] $values
|
||||
*/
|
||||
public function __construct(array $values, string ...$otherEncodingNames)
|
||||
{
|
||||
$this->values = $values;
|
||||
$this->otherEncodingNames = $otherEncodingNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primary value.
|
||||
*/
|
||||
public function getValue() : int
|
||||
{
|
||||
return $this->values[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets character set ECI by value.
|
||||
*
|
||||
* Returns the representing ECI of a given value, or null if it is legal but unsupported.
|
||||
*
|
||||
* @throws InvalidArgumentException if value is not between 0 and 900
|
||||
*/
|
||||
public static function getCharacterSetEciByValue(int $value) : ?self
|
||||
{
|
||||
if ($value < 0 || $value >= 900) {
|
||||
throw new InvalidArgumentException('Value must be between 0 and 900');
|
||||
}
|
||||
|
||||
$valueToEci = self::valueToEci();
|
||||
|
||||
if (! array_key_exists($value, $valueToEci)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $valueToEci[$value];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns character set ECI by name.
|
||||
*
|
||||
* Returns the representing ECI of a given name, or null if it is legal but unsupported
|
||||
*/
|
||||
public static function getCharacterSetEciByName(string $name) : ?self
|
||||
{
|
||||
$nameToEci = self::nameToEci();
|
||||
$name = strtolower($name);
|
||||
|
||||
if (! array_key_exists($name, $nameToEci)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $nameToEci[$name];
|
||||
}
|
||||
|
||||
private static function valueToEci() : array
|
||||
{
|
||||
if (null !== self::$valueToEci) {
|
||||
return self::$valueToEci;
|
||||
}
|
||||
|
||||
self::$valueToEci = [];
|
||||
|
||||
foreach (self::values() as $eci) {
|
||||
foreach ($eci->values as $value) {
|
||||
self::$valueToEci[$value] = $eci;
|
||||
}
|
||||
}
|
||||
|
||||
return self::$valueToEci;
|
||||
}
|
||||
|
||||
private static function nameToEci() : array
|
||||
{
|
||||
if (null !== self::$nameToEci) {
|
||||
return self::$nameToEci;
|
||||
}
|
||||
|
||||
self::$nameToEci = [];
|
||||
|
||||
foreach (self::values() as $eci) {
|
||||
self::$nameToEci[strtolower($eci->name())] = $eci;
|
||||
|
||||
foreach ($eci->otherEncodingNames as $name) {
|
||||
self::$nameToEci[strtolower($name)] = $eci;
|
||||
}
|
||||
}
|
||||
|
||||
return self::$nameToEci;
|
||||
}
|
||||
}
|
49
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/EcBlock.php
vendored
Normal file
49
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/EcBlock.php
vendored
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
/**
|
||||
* Encapsulates the parameters for one error-correction block in one symbol version.
|
||||
*
|
||||
* This includes the number of data codewords, and the number of times a block with these parameters is used
|
||||
* consecutively in the QR code version's format.
|
||||
*/
|
||||
final class EcBlock
|
||||
{
|
||||
/**
|
||||
* How many times the block is used.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $count;
|
||||
|
||||
/**
|
||||
* Number of data codewords.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $dataCodewords;
|
||||
|
||||
public function __construct(int $count, int $dataCodewords)
|
||||
{
|
||||
$this->count = $count;
|
||||
$this->dataCodewords = $dataCodewords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many times the block is used.
|
||||
*/
|
||||
public function getCount() : int
|
||||
{
|
||||
return $this->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of data codewords.
|
||||
*/
|
||||
public function getDataCodewords() : int
|
||||
{
|
||||
return $this->dataCodewords;
|
||||
}
|
||||
}
|
74
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/EcBlocks.php
vendored
Normal file
74
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/EcBlocks.php
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
/**
|
||||
* Encapsulates a set of error-correction blocks in one symbol version.
|
||||
*
|
||||
* Most versions will use blocks of differing sizes within one version, so, this encapsulates the parameters for each
|
||||
* set of blocks. It also holds the number of error-correction codewords per block since it will be the same across all
|
||||
* blocks within one version.
|
||||
*/
|
||||
final class EcBlocks
|
||||
{
|
||||
/**
|
||||
* Number of EC codewords per block.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $ecCodewordsPerBlock;
|
||||
|
||||
/**
|
||||
* List of EC blocks.
|
||||
*
|
||||
* @var EcBlock[]
|
||||
*/
|
||||
private $ecBlocks;
|
||||
|
||||
public function __construct(int $ecCodewordsPerBlock, EcBlock ...$ecBlocks)
|
||||
{
|
||||
$this->ecCodewordsPerBlock = $ecCodewordsPerBlock;
|
||||
$this->ecBlocks = $ecBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of EC codewords per block.
|
||||
*/
|
||||
public function getEcCodewordsPerBlock() : int
|
||||
{
|
||||
return $this->ecCodewordsPerBlock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of EC block appearances.
|
||||
*/
|
||||
public function getNumBlocks() : int
|
||||
{
|
||||
$total = 0;
|
||||
|
||||
foreach ($this->ecBlocks as $ecBlock) {
|
||||
$total += $ecBlock->getCount();
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total count of EC codewords.
|
||||
*/
|
||||
public function getTotalEcCodewords() : int
|
||||
{
|
||||
return $this->ecCodewordsPerBlock * $this->getNumBlocks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the EC blocks included in this collection.
|
||||
*
|
||||
* @return EcBlock[]
|
||||
*/
|
||||
public function getEcBlocks() : array
|
||||
{
|
||||
return $this->ecBlocks;
|
||||
}
|
||||
}
|
63
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php
vendored
Normal file
63
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/ErrorCorrectionLevel.php
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
use BaconQrCode\Exception\OutOfBoundsException;
|
||||
use DASPRiD\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Enum representing the four error correction levels.
|
||||
*
|
||||
* @method static self L() ~7% correction
|
||||
* @method static self M() ~15% correction
|
||||
* @method static self Q() ~25% correction
|
||||
* @method static self H() ~30% correction
|
||||
*/
|
||||
final class ErrorCorrectionLevel extends AbstractEnum
|
||||
{
|
||||
protected const L = [0x01];
|
||||
protected const M = [0x00];
|
||||
protected const Q = [0x03];
|
||||
protected const H = [0x02];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $bits;
|
||||
|
||||
protected function __construct(int $bits)
|
||||
{
|
||||
$this->bits = $bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws OutOfBoundsException if number of bits is invalid
|
||||
*/
|
||||
public static function forBits(int $bits) : self
|
||||
{
|
||||
switch ($bits) {
|
||||
case 0:
|
||||
return self::M();
|
||||
|
||||
case 1:
|
||||
return self::L();
|
||||
|
||||
case 2:
|
||||
return self::H();
|
||||
|
||||
case 3:
|
||||
return self::Q();
|
||||
}
|
||||
|
||||
throw new OutOfBoundsException('Invalid number of bits');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the two bits used to encode this error correction level.
|
||||
*/
|
||||
public function getBits() : int
|
||||
{
|
||||
return $this->bits;
|
||||
}
|
||||
}
|
203
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/FormatInformation.php
vendored
Normal file
203
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/FormatInformation.php
vendored
Normal file
|
@ -0,0 +1,203 @@
|
|||
<?php
|
||||
/**
|
||||
* BaconQrCode
|
||||
*
|
||||
* @link http://github.com/Bacon/BaconQrCode For the canonical source repository
|
||||
* @copyright 2013 Ben 'DASPRiD' Scholzen
|
||||
* @license http://opensource.org/licenses/BSD-2-Clause Simplified BSD License
|
||||
*/
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
/**
|
||||
* Encapsulates a QR Code's format information, including the data mask used and error correction level.
|
||||
*/
|
||||
class FormatInformation
|
||||
{
|
||||
/**
|
||||
* Mask for format information.
|
||||
*/
|
||||
private const FORMAT_INFO_MASK_QR = 0x5412;
|
||||
|
||||
/**
|
||||
* Lookup table for decoding format information.
|
||||
*
|
||||
* See ISO 18004:2006, Annex C, Table C.1
|
||||
*/
|
||||
private const FORMAT_INFO_DECODE_LOOKUP = [
|
||||
[0x5412, 0x00],
|
||||
[0x5125, 0x01],
|
||||
[0x5e7c, 0x02],
|
||||
[0x5b4b, 0x03],
|
||||
[0x45f9, 0x04],
|
||||
[0x40ce, 0x05],
|
||||
[0x4f97, 0x06],
|
||||
[0x4aa0, 0x07],
|
||||
[0x77c4, 0x08],
|
||||
[0x72f3, 0x09],
|
||||
[0x7daa, 0x0a],
|
||||
[0x789d, 0x0b],
|
||||
[0x662f, 0x0c],
|
||||
[0x6318, 0x0d],
|
||||
[0x6c41, 0x0e],
|
||||
[0x6976, 0x0f],
|
||||
[0x1689, 0x10],
|
||||
[0x13be, 0x11],
|
||||
[0x1ce7, 0x12],
|
||||
[0x19d0, 0x13],
|
||||
[0x0762, 0x14],
|
||||
[0x0255, 0x15],
|
||||
[0x0d0c, 0x16],
|
||||
[0x083b, 0x17],
|
||||
[0x355f, 0x18],
|
||||
[0x3068, 0x19],
|
||||
[0x3f31, 0x1a],
|
||||
[0x3a06, 0x1b],
|
||||
[0x24b4, 0x1c],
|
||||
[0x2183, 0x1d],
|
||||
[0x2eda, 0x1e],
|
||||
[0x2bed, 0x1f],
|
||||
];
|
||||
|
||||
/**
|
||||
* Offset i holds the number of 1 bits in the binary representation of i.
|
||||
*
|
||||
* @var int[]
|
||||
*/
|
||||
private const BITS_SET_IN_HALF_BYTE = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4];
|
||||
|
||||
/**
|
||||
* Error correction level.
|
||||
*
|
||||
* @var ErrorCorrectionLevel
|
||||
*/
|
||||
private $ecLevel;
|
||||
|
||||
/**
|
||||
* Data mask.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $dataMask;
|
||||
|
||||
protected function __construct(int $formatInfo)
|
||||
{
|
||||
$this->ecLevel = ErrorCorrectionLevel::forBits(($formatInfo >> 3) & 0x3);
|
||||
$this->dataMask = $formatInfo & 0x7;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks how many bits are different between two integers.
|
||||
*/
|
||||
public static function numBitsDiffering(int $a, int $b) : int
|
||||
{
|
||||
$a ^= $b;
|
||||
|
||||
return (
|
||||
self::BITS_SET_IN_HALF_BYTE[$a & 0xf]
|
||||
+ self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 4) & 0xf)]
|
||||
+ self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 8) & 0xf)]
|
||||
+ self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 12) & 0xf)]
|
||||
+ self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 16) & 0xf)]
|
||||
+ self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 20) & 0xf)]
|
||||
+ self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 24) & 0xf)]
|
||||
+ self::BITS_SET_IN_HALF_BYTE[(BitUtils::unsignedRightShift($a, 28) & 0xf)]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes format information.
|
||||
*/
|
||||
public static function decodeFormatInformation(int $maskedFormatInfo1, int $maskedFormatInfo2) : ?self
|
||||
{
|
||||
$formatInfo = self::doDecodeFormatInformation($maskedFormatInfo1, $maskedFormatInfo2);
|
||||
|
||||
if (null !== $formatInfo) {
|
||||
return $formatInfo;
|
||||
}
|
||||
|
||||
// Should return null, but, some QR codes apparently do not mask this info. Try again by actually masking the
|
||||
// pattern first.
|
||||
return self::doDecodeFormatInformation(
|
||||
$maskedFormatInfo1 ^ self::FORMAT_INFO_MASK_QR,
|
||||
$maskedFormatInfo2 ^ self::FORMAT_INFO_MASK_QR
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal method for decoding format information.
|
||||
*/
|
||||
private static function doDecodeFormatInformation(int $maskedFormatInfo1, int $maskedFormatInfo2) : ?self
|
||||
{
|
||||
$bestDifference = PHP_INT_MAX;
|
||||
$bestFormatInfo = 0;
|
||||
|
||||
foreach (self::FORMAT_INFO_DECODE_LOOKUP as $decodeInfo) {
|
||||
$targetInfo = $decodeInfo[0];
|
||||
|
||||
if ($targetInfo === $maskedFormatInfo1 || $targetInfo === $maskedFormatInfo2) {
|
||||
// Found an exact match
|
||||
return new self($decodeInfo[1]);
|
||||
}
|
||||
|
||||
$bitsDifference = self::numBitsDiffering($maskedFormatInfo1, $targetInfo);
|
||||
|
||||
if ($bitsDifference < $bestDifference) {
|
||||
$bestFormatInfo = $decodeInfo[1];
|
||||
$bestDifference = $bitsDifference;
|
||||
}
|
||||
|
||||
if ($maskedFormatInfo1 !== $maskedFormatInfo2) {
|
||||
// Also try the other option
|
||||
$bitsDifference = self::numBitsDiffering($maskedFormatInfo2, $targetInfo);
|
||||
|
||||
if ($bitsDifference < $bestDifference) {
|
||||
$bestFormatInfo = $decodeInfo[1];
|
||||
$bestDifference = $bitsDifference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits differing means we found a match.
|
||||
if ($bestDifference <= 3) {
|
||||
return new self($bestFormatInfo);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the error correction level.
|
||||
*/
|
||||
public function getErrorCorrectionLevel() : ErrorCorrectionLevel
|
||||
{
|
||||
return $this->ecLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data mask.
|
||||
*/
|
||||
public function getDataMask() : int
|
||||
{
|
||||
return $this->dataMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hashes the code of the EC level.
|
||||
*/
|
||||
public function hashCode() : int
|
||||
{
|
||||
return ($this->ecLevel->getBits() << 3) | $this->dataMask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if this instance equals another one.
|
||||
*/
|
||||
public function equals(self $other) : bool
|
||||
{
|
||||
return (
|
||||
$this->ecLevel === $other->ecLevel
|
||||
&& $this->dataMask === $other->dataMask
|
||||
);
|
||||
}
|
||||
}
|
79
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/Mode.php
vendored
Normal file
79
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/Mode.php
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
use DASPRiD\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* Enum representing various modes in which data can be encoded to bits.
|
||||
*
|
||||
* @method static self TERMINATOR()
|
||||
* @method static self NUMERIC()
|
||||
* @method static self ALPHANUMERIC()
|
||||
* @method static self STRUCTURED_APPEND()
|
||||
* @method static self BYTE()
|
||||
* @method static self ECI()
|
||||
* @method static self KANJI()
|
||||
* @method static self FNC1_FIRST_POSITION()
|
||||
* @method static self FNC1_SECOND_POSITION()
|
||||
* @method static self HANZI()
|
||||
*/
|
||||
final class Mode extends AbstractEnum
|
||||
{
|
||||
protected const TERMINATOR = [[0, 0, 0], 0x00];
|
||||
protected const NUMERIC = [[10, 12, 14], 0x01];
|
||||
protected const ALPHANUMERIC = [[9, 11, 13], 0x02];
|
||||
protected const STRUCTURED_APPEND = [[0, 0, 0], 0x03];
|
||||
protected const BYTE = [[8, 16, 16], 0x04];
|
||||
protected const ECI = [[0, 0, 0], 0x07];
|
||||
protected const KANJI = [[8, 10, 12], 0x08];
|
||||
protected const FNC1_FIRST_POSITION = [[0, 0, 0], 0x05];
|
||||
protected const FNC1_SECOND_POSITION = [[0, 0, 0], 0x09];
|
||||
protected const HANZI = [[8, 10, 12], 0x0d];
|
||||
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
private $characterCountBitsForVersions;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $bits;
|
||||
|
||||
/**
|
||||
* @param int[] $characterCountBitsForVersions
|
||||
*/
|
||||
protected function __construct(array $characterCountBitsForVersions, int $bits)
|
||||
{
|
||||
$this->characterCountBitsForVersions = $characterCountBitsForVersions;
|
||||
$this->bits = $bits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of bits used in a specific QR code version.
|
||||
*/
|
||||
public function getCharacterCountBits(Version $version) : int
|
||||
{
|
||||
$number = $version->getVersionNumber();
|
||||
|
||||
if ($number <= 9) {
|
||||
$offset = 0;
|
||||
} elseif ($number <= 26) {
|
||||
$offset = 1;
|
||||
} else {
|
||||
$offset = 2;
|
||||
}
|
||||
|
||||
return $this->characterCountBitsForVersions[$offset];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the four bits used to encode this mode.
|
||||
*/
|
||||
public function getBits() : int
|
||||
{
|
||||
return $this->bits;
|
||||
}
|
||||
}
|
468
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php
vendored
Normal file
468
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/ReedSolomonCodec.php
vendored
Normal file
|
@ -0,0 +1,468 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
use BaconQrCode\Exception\RuntimeException;
|
||||
use SplFixedArray;
|
||||
|
||||
/**
|
||||
* Reed-Solomon codec for 8-bit characters.
|
||||
*
|
||||
* Based on libfec by Phil Karn, KA9Q.
|
||||
*/
|
||||
final class ReedSolomonCodec
|
||||
{
|
||||
/**
|
||||
* Symbol size in bits.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $symbolSize;
|
||||
|
||||
/**
|
||||
* Block size in symbols.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $blockSize;
|
||||
|
||||
/**
|
||||
* First root of RS code generator polynomial, index form.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $firstRoot;
|
||||
|
||||
/**
|
||||
* Primitive element to generate polynomial roots, index form.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $primitive;
|
||||
|
||||
/**
|
||||
* Prim-th root of 1, index form.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $iPrimitive;
|
||||
|
||||
/**
|
||||
* RS code generator polynomial degree (number of roots).
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $numRoots;
|
||||
|
||||
/**
|
||||
* Padding bytes at front of shortened block.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $padding;
|
||||
|
||||
/**
|
||||
* Log lookup table.
|
||||
*
|
||||
* @var SplFixedArray
|
||||
*/
|
||||
private $alphaTo;
|
||||
|
||||
/**
|
||||
* Anti-Log lookup table.
|
||||
*
|
||||
* @var SplFixedArray
|
||||
*/
|
||||
private $indexOf;
|
||||
|
||||
/**
|
||||
* Generator polynomial.
|
||||
*
|
||||
* @var SplFixedArray
|
||||
*/
|
||||
private $generatorPoly;
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if symbol size ist not between 0 and 8
|
||||
* @throws InvalidArgumentException if first root is invalid
|
||||
* @throws InvalidArgumentException if num roots is invalid
|
||||
* @throws InvalidArgumentException if padding is invalid
|
||||
* @throws RuntimeException if field generator polynomial is not primitive
|
||||
*/
|
||||
public function __construct(
|
||||
int $symbolSize,
|
||||
int $gfPoly,
|
||||
int $firstRoot,
|
||||
int $primitive,
|
||||
int $numRoots,
|
||||
int $padding
|
||||
) {
|
||||
if ($symbolSize < 0 || $symbolSize > 8) {
|
||||
throw new InvalidArgumentException('Symbol size must be between 0 and 8');
|
||||
}
|
||||
|
||||
if ($firstRoot < 0 || $firstRoot >= (1 << $symbolSize)) {
|
||||
throw new InvalidArgumentException('First root must be between 0 and ' . (1 << $symbolSize));
|
||||
}
|
||||
|
||||
if ($numRoots < 0 || $numRoots >= (1 << $symbolSize)) {
|
||||
throw new InvalidArgumentException('Num roots must be between 0 and ' . (1 << $symbolSize));
|
||||
}
|
||||
|
||||
if ($padding < 0 || $padding >= ((1 << $symbolSize) - 1 - $numRoots)) {
|
||||
throw new InvalidArgumentException(
|
||||
'Padding must be between 0 and ' . ((1 << $symbolSize) - 1 - $numRoots)
|
||||
);
|
||||
}
|
||||
|
||||
$this->symbolSize = $symbolSize;
|
||||
$this->blockSize = (1 << $symbolSize) - 1;
|
||||
$this->padding = $padding;
|
||||
$this->alphaTo = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0), false);
|
||||
$this->indexOf = SplFixedArray::fromArray(array_fill(0, $this->blockSize + 1, 0), false);
|
||||
|
||||
// Generate galous field lookup table
|
||||
$this->indexOf[0] = $this->blockSize;
|
||||
$this->alphaTo[$this->blockSize] = 0;
|
||||
|
||||
$sr = 1;
|
||||
|
||||
for ($i = 0; $i < $this->blockSize; ++$i) {
|
||||
$this->indexOf[$sr] = $i;
|
||||
$this->alphaTo[$i] = $sr;
|
||||
|
||||
$sr <<= 1;
|
||||
|
||||
if ($sr & (1 << $symbolSize)) {
|
||||
$sr ^= $gfPoly;
|
||||
}
|
||||
|
||||
$sr &= $this->blockSize;
|
||||
}
|
||||
|
||||
if (1 !== $sr) {
|
||||
throw new RuntimeException('Field generator polynomial is not primitive');
|
||||
}
|
||||
|
||||
// Form RS code generator polynomial from its roots
|
||||
$this->generatorPoly = SplFixedArray::fromArray(array_fill(0, $numRoots + 1, 0), false);
|
||||
$this->firstRoot = $firstRoot;
|
||||
$this->primitive = $primitive;
|
||||
$this->numRoots = $numRoots;
|
||||
|
||||
// Find prim-th root of 1, used in decoding
|
||||
for ($iPrimitive = 1; ($iPrimitive % $primitive) !== 0; $iPrimitive += $this->blockSize) {
|
||||
}
|
||||
|
||||
$this->iPrimitive = intdiv($iPrimitive, $primitive);
|
||||
|
||||
$this->generatorPoly[0] = 1;
|
||||
|
||||
for ($i = 0, $root = $firstRoot * $primitive; $i < $numRoots; ++$i, $root += $primitive) {
|
||||
$this->generatorPoly[$i + 1] = 1;
|
||||
|
||||
for ($j = $i; $j > 0; $j--) {
|
||||
if ($this->generatorPoly[$j] !== 0) {
|
||||
$this->generatorPoly[$j] = $this->generatorPoly[$j - 1] ^ $this->alphaTo[
|
||||
$this->modNn($this->indexOf[$this->generatorPoly[$j]] + $root)
|
||||
];
|
||||
} else {
|
||||
$this->generatorPoly[$j] = $this->generatorPoly[$j - 1];
|
||||
}
|
||||
}
|
||||
|
||||
$this->generatorPoly[$j] = $this->alphaTo[$this->modNn($this->indexOf[$this->generatorPoly[0]] + $root)];
|
||||
}
|
||||
|
||||
// Convert generator poly to index form for quicker encoding
|
||||
for ($i = 0; $i <= $numRoots; ++$i) {
|
||||
$this->generatorPoly[$i] = $this->indexOf[$this->generatorPoly[$i]];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes data and writes result back into parity array.
|
||||
*/
|
||||
public function encode(SplFixedArray $data, SplFixedArray $parity) : void
|
||||
{
|
||||
for ($i = 0; $i < $this->numRoots; ++$i) {
|
||||
$parity[$i] = 0;
|
||||
}
|
||||
|
||||
$iterations = $this->blockSize - $this->numRoots - $this->padding;
|
||||
|
||||
for ($i = 0; $i < $iterations; ++$i) {
|
||||
$feedback = $this->indexOf[$data[$i] ^ $parity[0]];
|
||||
|
||||
if ($feedback !== $this->blockSize) {
|
||||
// Feedback term is non-zero
|
||||
$feedback = $this->modNn($this->blockSize - $this->generatorPoly[$this->numRoots] + $feedback);
|
||||
|
||||
for ($j = 1; $j < $this->numRoots; ++$j) {
|
||||
$parity[$j] = $parity[$j] ^ $this->alphaTo[
|
||||
$this->modNn($feedback + $this->generatorPoly[$this->numRoots - $j])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
for ($j = 0; $j < $this->numRoots - 1; ++$j) {
|
||||
$parity[$j] = $parity[$j + 1];
|
||||
}
|
||||
|
||||
if ($feedback !== $this->blockSize) {
|
||||
$parity[$this->numRoots - 1] = $this->alphaTo[$this->modNn($feedback + $this->generatorPoly[0])];
|
||||
} else {
|
||||
$parity[$this->numRoots - 1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes received data.
|
||||
*/
|
||||
public function decode(SplFixedArray $data, SplFixedArray $erasures = null) : ?int
|
||||
{
|
||||
// This speeds up the initialization a bit.
|
||||
$numRootsPlusOne = SplFixedArray::fromArray(array_fill(0, $this->numRoots + 1, 0), false);
|
||||
$numRoots = SplFixedArray::fromArray(array_fill(0, $this->numRoots, 0), false);
|
||||
|
||||
$lambda = clone $numRootsPlusOne;
|
||||
$b = clone $numRootsPlusOne;
|
||||
$t = clone $numRootsPlusOne;
|
||||
$omega = clone $numRootsPlusOne;
|
||||
$root = clone $numRoots;
|
||||
$loc = clone $numRoots;
|
||||
|
||||
$numErasures = (null !== $erasures ? count($erasures) : 0);
|
||||
|
||||
// Form the Syndromes; i.e., evaluate data(x) at roots of g(x)
|
||||
$syndromes = SplFixedArray::fromArray(array_fill(0, $this->numRoots, $data[0]), false);
|
||||
|
||||
for ($i = 1; $i < $this->blockSize - $this->padding; ++$i) {
|
||||
for ($j = 0; $j < $this->numRoots; ++$j) {
|
||||
if ($syndromes[$j] === 0) {
|
||||
$syndromes[$j] = $data[$i];
|
||||
} else {
|
||||
$syndromes[$j] = $data[$i] ^ $this->alphaTo[
|
||||
$this->modNn($this->indexOf[$syndromes[$j]] + ($this->firstRoot + $j) * $this->primitive)
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Convert syndromes to index form, checking for nonzero conditions
|
||||
$syndromeError = 0;
|
||||
|
||||
for ($i = 0; $i < $this->numRoots; ++$i) {
|
||||
$syndromeError |= $syndromes[$i];
|
||||
$syndromes[$i] = $this->indexOf[$syndromes[$i]];
|
||||
}
|
||||
|
||||
if (! $syndromeError) {
|
||||
// If syndrome is zero, data[] is a codeword and there are no errors to correct, so return data[]
|
||||
// unmodified.
|
||||
return 0;
|
||||
}
|
||||
|
||||
$lambda[0] = 1;
|
||||
|
||||
if ($numErasures > 0) {
|
||||
// Init lambda to be the erasure locator polynomial
|
||||
$lambda[1] = $this->alphaTo[$this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[0]))];
|
||||
|
||||
for ($i = 1; $i < $numErasures; ++$i) {
|
||||
$u = $this->modNn($this->primitive * ($this->blockSize - 1 - $erasures[$i]));
|
||||
|
||||
for ($j = $i + 1; $j > 0; --$j) {
|
||||
$tmp = $this->indexOf[$lambda[$j - 1]];
|
||||
|
||||
if ($tmp !== $this->blockSize) {
|
||||
$lambda[$j] = $lambda[$j] ^ $this->alphaTo[$this->modNn($u + $tmp)];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0; $i <= $this->numRoots; ++$i) {
|
||||
$b[$i] = $this->indexOf[$lambda[$i]];
|
||||
}
|
||||
|
||||
// Begin Berlekamp-Massey algorithm to determine error+erasure locator polynomial
|
||||
$r = $numErasures;
|
||||
$el = $numErasures;
|
||||
|
||||
while (++$r <= $this->numRoots) {
|
||||
// Compute discrepancy at the r-th step in poly form
|
||||
$discrepancyR = 0;
|
||||
|
||||
for ($i = 0; $i < $r; ++$i) {
|
||||
if ($lambda[$i] !== 0 && $syndromes[$r - $i - 1] !== $this->blockSize) {
|
||||
$discrepancyR ^= $this->alphaTo[
|
||||
$this->modNn($this->indexOf[$lambda[$i]] + $syndromes[$r - $i - 1])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$discrepancyR = $this->indexOf[$discrepancyR];
|
||||
|
||||
if ($discrepancyR === $this->blockSize) {
|
||||
$tmp = $b->toArray();
|
||||
array_unshift($tmp, $this->blockSize);
|
||||
array_pop($tmp);
|
||||
$b = SplFixedArray::fromArray($tmp, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
$t[0] = $lambda[0];
|
||||
|
||||
for ($i = 0; $i < $this->numRoots; ++$i) {
|
||||
if ($b[$i] !== $this->blockSize) {
|
||||
$t[$i + 1] = $lambda[$i + 1] ^ $this->alphaTo[$this->modNn($discrepancyR + $b[$i])];
|
||||
} else {
|
||||
$t[$i + 1] = $lambda[$i + 1];
|
||||
}
|
||||
}
|
||||
|
||||
if (2 * $el <= $r + $numErasures - 1) {
|
||||
$el = $r + $numErasures - $el;
|
||||
|
||||
for ($i = 0; $i <= $this->numRoots; ++$i) {
|
||||
$b[$i] = (
|
||||
$lambda[$i] === 0
|
||||
? $this->blockSize
|
||||
: $this->modNn($this->indexOf[$lambda[$i]] - $discrepancyR + $this->blockSize)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$tmp = $b->toArray();
|
||||
array_unshift($tmp, $this->blockSize);
|
||||
array_pop($tmp);
|
||||
$b = SplFixedArray::fromArray($tmp, false);
|
||||
}
|
||||
|
||||
$lambda = clone $t;
|
||||
}
|
||||
|
||||
// Convert lambda to index form and compute deg(lambda(x))
|
||||
$degLambda = 0;
|
||||
|
||||
for ($i = 0; $i <= $this->numRoots; ++$i) {
|
||||
$lambda[$i] = $this->indexOf[$lambda[$i]];
|
||||
|
||||
if ($lambda[$i] !== $this->blockSize) {
|
||||
$degLambda = $i;
|
||||
}
|
||||
}
|
||||
|
||||
// Find roots of the error+erasure locator polynomial by Chien search.
|
||||
$reg = clone $lambda;
|
||||
$reg[0] = 0;
|
||||
$count = 0;
|
||||
$i = 1;
|
||||
|
||||
for ($k = $this->iPrimitive - 1; $i <= $this->blockSize; ++$i, $k = $this->modNn($k + $this->iPrimitive)) {
|
||||
$q = 1;
|
||||
|
||||
for ($j = $degLambda; $j > 0; $j--) {
|
||||
if ($reg[$j] !== $this->blockSize) {
|
||||
$reg[$j] = $this->modNn($reg[$j] + $j);
|
||||
$q ^= $this->alphaTo[$reg[$j]];
|
||||
}
|
||||
}
|
||||
|
||||
if ($q !== 0) {
|
||||
// Not a root
|
||||
continue;
|
||||
}
|
||||
|
||||
// Store root (index-form) and error location number
|
||||
$root[$count] = $i;
|
||||
$loc[$count] = $k;
|
||||
|
||||
if (++$count === $degLambda) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($degLambda !== $count) {
|
||||
// deg(lambda) unequal to number of roots: uncorrectable error detected
|
||||
return null;
|
||||
}
|
||||
|
||||
// Compute err+eras evaluate poly omega(x) = s(x)*lambda(x) (modulo x**numRoots). In index form. Also find
|
||||
// deg(omega).
|
||||
$degOmega = $degLambda - 1;
|
||||
|
||||
for ($i = 0; $i <= $degOmega; ++$i) {
|
||||
$tmp = 0;
|
||||
|
||||
for ($j = $i; $j >= 0; --$j) {
|
||||
if ($syndromes[$i - $j] !== $this->blockSize && $lambda[$j] !== $this->blockSize) {
|
||||
$tmp ^= $this->alphaTo[$this->modNn($syndromes[$i - $j] + $lambda[$j])];
|
||||
}
|
||||
}
|
||||
|
||||
$omega[$i] = $this->indexOf[$tmp];
|
||||
}
|
||||
|
||||
// Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = inv(X(l))**(firstRoot-1) and
|
||||
// den = lambda_pr(inv(X(l))) all in poly form.
|
||||
for ($j = $count - 1; $j >= 0; --$j) {
|
||||
$num1 = 0;
|
||||
|
||||
for ($i = $degOmega; $i >= 0; $i--) {
|
||||
if ($omega[$i] !== $this->blockSize) {
|
||||
$num1 ^= $this->alphaTo[$this->modNn($omega[$i] + $i * $root[$j])];
|
||||
}
|
||||
}
|
||||
|
||||
$num2 = $this->alphaTo[$this->modNn($root[$j] * ($this->firstRoot - 1) + $this->blockSize)];
|
||||
$den = 0;
|
||||
|
||||
// lambda[i+1] for i even is the formal derivativelambda_pr of lambda[i]
|
||||
for ($i = min($degLambda, $this->numRoots - 1) & ~1; $i >= 0; $i -= 2) {
|
||||
if ($lambda[$i + 1] !== $this->blockSize) {
|
||||
$den ^= $this->alphaTo[$this->modNn($lambda[$i + 1] + $i * $root[$j])];
|
||||
}
|
||||
}
|
||||
|
||||
// Apply error to data
|
||||
if ($num1 !== 0 && $loc[$j] >= $this->padding) {
|
||||
$data[$loc[$j] - $this->padding] = $data[$loc[$j] - $this->padding] ^ (
|
||||
$this->alphaTo[
|
||||
$this->modNn(
|
||||
$this->indexOf[$num1] + $this->indexOf[$num2] + $this->blockSize - $this->indexOf[$den]
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (null !== $erasures) {
|
||||
if (count($erasures) < $count) {
|
||||
$erasures->setSize($count);
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$erasures[$i] = $loc[$i];
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes $x % GF_SIZE, where GF_SIZE is 2**GF_BITS - 1, without a slow divide.
|
||||
*/
|
||||
private function modNn(int $x) : int
|
||||
{
|
||||
while ($x >= $this->blockSize) {
|
||||
$x -= $this->blockSize;
|
||||
$x = ($x >> $this->symbolSize) + ($x & $this->blockSize);
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
}
|
596
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/Version.php
vendored
Normal file
596
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Common/Version.php
vendored
Normal file
|
@ -0,0 +1,596 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Common;
|
||||
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
use SplFixedArray;
|
||||
|
||||
/**
|
||||
* Version representation.
|
||||
*/
|
||||
final class Version
|
||||
{
|
||||
private const VERSION_DECODE_INFO = [
|
||||
0x07c94,
|
||||
0x085bc,
|
||||
0x09a99,
|
||||
0x0a4d3,
|
||||
0x0bbf6,
|
||||
0x0c762,
|
||||
0x0d847,
|
||||
0x0e60d,
|
||||
0x0f928,
|
||||
0x10b78,
|
||||
0x1145d,
|
||||
0x12a17,
|
||||
0x13532,
|
||||
0x149a6,
|
||||
0x15683,
|
||||
0x168c9,
|
||||
0x177ec,
|
||||
0x18ec4,
|
||||
0x191e1,
|
||||
0x1afab,
|
||||
0x1b08e,
|
||||
0x1cc1a,
|
||||
0x1d33f,
|
||||
0x1ed75,
|
||||
0x1f250,
|
||||
0x209d5,
|
||||
0x216f0,
|
||||
0x228ba,
|
||||
0x2379f,
|
||||
0x24b0b,
|
||||
0x2542e,
|
||||
0x26a64,
|
||||
0x27541,
|
||||
0x28c69,
|
||||
];
|
||||
|
||||
/**
|
||||
* Version number of this version.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $versionNumber;
|
||||
|
||||
/**
|
||||
* Alignment pattern centers.
|
||||
*
|
||||
* @var SplFixedArray
|
||||
*/
|
||||
private $alignmentPatternCenters;
|
||||
|
||||
/**
|
||||
* Error correction blocks.
|
||||
*
|
||||
* @var EcBlocks[]
|
||||
*/
|
||||
private $ecBlocks;
|
||||
|
||||
/**
|
||||
* Total number of codewords.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $totalCodewords;
|
||||
|
||||
/**
|
||||
* Cached version instances.
|
||||
*
|
||||
* @var array<int, self>|null
|
||||
*/
|
||||
private static $versions;
|
||||
|
||||
/**
|
||||
* @param int[] $alignmentPatternCenters
|
||||
*/
|
||||
private function __construct(
|
||||
int $versionNumber,
|
||||
array $alignmentPatternCenters,
|
||||
EcBlocks ...$ecBlocks
|
||||
) {
|
||||
$this->versionNumber = $versionNumber;
|
||||
$this->alignmentPatternCenters = $alignmentPatternCenters;
|
||||
$this->ecBlocks = $ecBlocks;
|
||||
|
||||
$totalCodewords = 0;
|
||||
$ecCodewords = $ecBlocks[0]->getEcCodewordsPerBlock();
|
||||
|
||||
foreach ($ecBlocks[0]->getEcBlocks() as $ecBlock) {
|
||||
$totalCodewords += $ecBlock->getCount() * ($ecBlock->getDataCodewords() + $ecCodewords);
|
||||
}
|
||||
|
||||
$this->totalCodewords = $totalCodewords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the version number.
|
||||
*/
|
||||
public function getVersionNumber() : int
|
||||
{
|
||||
return $this->versionNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the alignment pattern centers.
|
||||
*
|
||||
* @return int[]
|
||||
*/
|
||||
public function getAlignmentPatternCenters() : array
|
||||
{
|
||||
return $this->alignmentPatternCenters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of codewords.
|
||||
*/
|
||||
public function getTotalCodewords() : int
|
||||
{
|
||||
return $this->totalCodewords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the dimension for the current version.
|
||||
*/
|
||||
public function getDimensionForVersion() : int
|
||||
{
|
||||
return 17 + 4 * $this->versionNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of EC blocks for a specific EC level.
|
||||
*/
|
||||
public function getEcBlocksForLevel(ErrorCorrectionLevel $ecLevel) : EcBlocks
|
||||
{
|
||||
return $this->ecBlocks[$ecLevel->ordinal()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a provisional version number for a specific dimension.
|
||||
*
|
||||
* @throws InvalidArgumentException if dimension is not 1 mod 4
|
||||
*/
|
||||
public static function getProvisionalVersionForDimension(int $dimension) : self
|
||||
{
|
||||
if (1 !== $dimension % 4) {
|
||||
throw new InvalidArgumentException('Dimension is not 1 mod 4');
|
||||
}
|
||||
|
||||
return self::getVersionForNumber(intdiv($dimension - 17, 4));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a version instance for a specific version number.
|
||||
*
|
||||
* @throws InvalidArgumentException if version number is out of range
|
||||
*/
|
||||
public static function getVersionForNumber(int $versionNumber) : self
|
||||
{
|
||||
if ($versionNumber < 1 || $versionNumber > 40) {
|
||||
throw new InvalidArgumentException('Version number must be between 1 and 40');
|
||||
}
|
||||
|
||||
return self::versions()[$versionNumber - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes version information from an integer and returns the version.
|
||||
*/
|
||||
public static function decodeVersionInformation(int $versionBits) : ?self
|
||||
{
|
||||
$bestDifference = PHP_INT_MAX;
|
||||
$bestVersion = 0;
|
||||
|
||||
foreach (self::VERSION_DECODE_INFO as $i => $targetVersion) {
|
||||
if ($targetVersion === $versionBits) {
|
||||
return self::getVersionForNumber($i + 7);
|
||||
}
|
||||
|
||||
$bitsDifference = FormatInformation::numBitsDiffering($versionBits, $targetVersion);
|
||||
|
||||
if ($bitsDifference < $bestDifference) {
|
||||
$bestVersion = $i + 7;
|
||||
$bestDifference = $bitsDifference;
|
||||
}
|
||||
}
|
||||
|
||||
if ($bestDifference <= 3) {
|
||||
return self::getVersionForNumber($bestVersion);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the function pattern for the current version.
|
||||
*/
|
||||
public function buildFunctionPattern() : BitMatrix
|
||||
{
|
||||
$dimension = $this->getDimensionForVersion();
|
||||
$bitMatrix = new BitMatrix($dimension);
|
||||
|
||||
// Top left finder pattern + separator + format
|
||||
$bitMatrix->setRegion(0, 0, 9, 9);
|
||||
// Top right finder pattern + separator + format
|
||||
$bitMatrix->setRegion($dimension - 8, 0, 8, 9);
|
||||
// Bottom left finder pattern + separator + format
|
||||
$bitMatrix->setRegion(0, $dimension - 8, 9, 8);
|
||||
|
||||
// Alignment patterns
|
||||
$max = count($this->alignmentPatternCenters);
|
||||
|
||||
for ($x = 0; $x < $max; ++$x) {
|
||||
$i = $this->alignmentPatternCenters[$x] - 2;
|
||||
|
||||
for ($y = 0; $y < $max; ++$y) {
|
||||
if (($x === 0 && ($y === 0 || $y === $max - 1)) || ($x === $max - 1 && $y === 0)) {
|
||||
// No alignment patterns near the three finder paterns
|
||||
continue;
|
||||
}
|
||||
|
||||
$bitMatrix->setRegion($this->alignmentPatternCenters[$y] - 2, $i, 5, 5);
|
||||
}
|
||||
}
|
||||
|
||||
// Vertical timing pattern
|
||||
$bitMatrix->setRegion(6, 9, 1, $dimension - 17);
|
||||
// Horizontal timing pattern
|
||||
$bitMatrix->setRegion(9, 6, $dimension - 17, 1);
|
||||
|
||||
if ($this->versionNumber > 6) {
|
||||
// Version info, top right
|
||||
$bitMatrix->setRegion($dimension - 11, 0, 3, 6);
|
||||
// Version info, bottom left
|
||||
$bitMatrix->setRegion(0, $dimension - 11, 6, 3);
|
||||
}
|
||||
|
||||
return $bitMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation for the version.
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
return (string) $this->versionNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build and cache a specific version.
|
||||
*
|
||||
* See ISO 18004:2006 6.5.1 Table 9.
|
||||
*
|
||||
* @return array<int, self>
|
||||
*/
|
||||
private static function versions() : array
|
||||
{
|
||||
if (null !== self::$versions) {
|
||||
return self::$versions;
|
||||
}
|
||||
|
||||
return self::$versions = [
|
||||
new self(
|
||||
1,
|
||||
[],
|
||||
new EcBlocks(7, new EcBlock(1, 19)),
|
||||
new EcBlocks(10, new EcBlock(1, 16)),
|
||||
new EcBlocks(13, new EcBlock(1, 13)),
|
||||
new EcBlocks(17, new EcBlock(1, 9))
|
||||
),
|
||||
new self(
|
||||
2,
|
||||
[6, 18],
|
||||
new EcBlocks(10, new EcBlock(1, 34)),
|
||||
new EcBlocks(16, new EcBlock(1, 28)),
|
||||
new EcBlocks(22, new EcBlock(1, 22)),
|
||||
new EcBlocks(28, new EcBlock(1, 16))
|
||||
),
|
||||
new self(
|
||||
3,
|
||||
[6, 22],
|
||||
new EcBlocks(15, new EcBlock(1, 55)),
|
||||
new EcBlocks(26, new EcBlock(1, 44)),
|
||||
new EcBlocks(18, new EcBlock(2, 17)),
|
||||
new EcBlocks(22, new EcBlock(2, 13))
|
||||
),
|
||||
new self(
|
||||
4,
|
||||
[6, 26],
|
||||
new EcBlocks(20, new EcBlock(1, 80)),
|
||||
new EcBlocks(18, new EcBlock(2, 32)),
|
||||
new EcBlocks(26, new EcBlock(3, 24)),
|
||||
new EcBlocks(16, new EcBlock(4, 9))
|
||||
),
|
||||
new self(
|
||||
5,
|
||||
[6, 30],
|
||||
new EcBlocks(26, new EcBlock(1, 108)),
|
||||
new EcBlocks(24, new EcBlock(2, 43)),
|
||||
new EcBlocks(18, new EcBlock(2, 15), new EcBlock(2, 16)),
|
||||
new EcBlocks(22, new EcBlock(2, 11), new EcBlock(2, 12))
|
||||
),
|
||||
new self(
|
||||
6,
|
||||
[6, 34],
|
||||
new EcBlocks(18, new EcBlock(2, 68)),
|
||||
new EcBlocks(16, new EcBlock(4, 27)),
|
||||
new EcBlocks(24, new EcBlock(4, 19)),
|
||||
new EcBlocks(28, new EcBlock(4, 15))
|
||||
),
|
||||
new self(
|
||||
7,
|
||||
[6, 22, 38],
|
||||
new EcBlocks(20, new EcBlock(2, 78)),
|
||||
new EcBlocks(18, new EcBlock(4, 31)),
|
||||
new EcBlocks(18, new EcBlock(2, 14), new EcBlock(4, 15)),
|
||||
new EcBlocks(26, new EcBlock(4, 13), new EcBlock(1, 14))
|
||||
),
|
||||
new self(
|
||||
8,
|
||||
[6, 24, 42],
|
||||
new EcBlocks(24, new EcBlock(2, 97)),
|
||||
new EcBlocks(22, new EcBlock(2, 38), new EcBlock(2, 39)),
|
||||
new EcBlocks(22, new EcBlock(4, 18), new EcBlock(2, 19)),
|
||||
new EcBlocks(26, new EcBlock(4, 14), new EcBlock(2, 15))
|
||||
),
|
||||
new self(
|
||||
9,
|
||||
[6, 26, 46],
|
||||
new EcBlocks(30, new EcBlock(2, 116)),
|
||||
new EcBlocks(22, new EcBlock(3, 36), new EcBlock(2, 37)),
|
||||
new EcBlocks(20, new EcBlock(4, 16), new EcBlock(4, 17)),
|
||||
new EcBlocks(24, new EcBlock(4, 12), new EcBlock(4, 13))
|
||||
),
|
||||
new self(
|
||||
10,
|
||||
[6, 28, 50],
|
||||
new EcBlocks(18, new EcBlock(2, 68), new EcBlock(2, 69)),
|
||||
new EcBlocks(26, new EcBlock(4, 43), new EcBlock(1, 44)),
|
||||
new EcBlocks(24, new EcBlock(6, 19), new EcBlock(2, 20)),
|
||||
new EcBlocks(28, new EcBlock(6, 15), new EcBlock(2, 16))
|
||||
),
|
||||
new self(
|
||||
11,
|
||||
[6, 30, 54],
|
||||
new EcBlocks(20, new EcBlock(4, 81)),
|
||||
new EcBlocks(30, new EcBlock(1, 50), new EcBlock(4, 51)),
|
||||
new EcBlocks(28, new EcBlock(4, 22), new EcBlock(4, 23)),
|
||||
new EcBlocks(24, new EcBlock(3, 12), new EcBlock(8, 13))
|
||||
),
|
||||
new self(
|
||||
12,
|
||||
[6, 32, 58],
|
||||
new EcBlocks(24, new EcBlock(2, 92), new EcBlock(2, 93)),
|
||||
new EcBlocks(22, new EcBlock(6, 36), new EcBlock(2, 37)),
|
||||
new EcBlocks(26, new EcBlock(4, 20), new EcBlock(6, 21)),
|
||||
new EcBlocks(28, new EcBlock(7, 14), new EcBlock(4, 15))
|
||||
),
|
||||
new self(
|
||||
13,
|
||||
[6, 34, 62],
|
||||
new EcBlocks(26, new EcBlock(4, 107)),
|
||||
new EcBlocks(22, new EcBlock(8, 37), new EcBlock(1, 38)),
|
||||
new EcBlocks(24, new EcBlock(8, 20), new EcBlock(4, 21)),
|
||||
new EcBlocks(22, new EcBlock(12, 11), new EcBlock(4, 12))
|
||||
),
|
||||
new self(
|
||||
14,
|
||||
[6, 26, 46, 66],
|
||||
new EcBlocks(30, new EcBlock(3, 115), new EcBlock(1, 116)),
|
||||
new EcBlocks(24, new EcBlock(4, 40), new EcBlock(5, 41)),
|
||||
new EcBlocks(20, new EcBlock(11, 16), new EcBlock(5, 17)),
|
||||
new EcBlocks(24, new EcBlock(11, 12), new EcBlock(5, 13))
|
||||
),
|
||||
new self(
|
||||
15,
|
||||
[6, 26, 48, 70],
|
||||
new EcBlocks(22, new EcBlock(5, 87), new EcBlock(1, 88)),
|
||||
new EcBlocks(24, new EcBlock(5, 41), new EcBlock(5, 42)),
|
||||
new EcBlocks(30, new EcBlock(5, 24), new EcBlock(7, 25)),
|
||||
new EcBlocks(24, new EcBlock(11, 12), new EcBlock(7, 13))
|
||||
),
|
||||
new self(
|
||||
16,
|
||||
[6, 26, 50, 74],
|
||||
new EcBlocks(24, new EcBlock(5, 98), new EcBlock(1, 99)),
|
||||
new EcBlocks(28, new EcBlock(7, 45), new EcBlock(3, 46)),
|
||||
new EcBlocks(24, new EcBlock(15, 19), new EcBlock(2, 20)),
|
||||
new EcBlocks(30, new EcBlock(3, 15), new EcBlock(13, 16))
|
||||
),
|
||||
new self(
|
||||
17,
|
||||
[6, 30, 54, 78],
|
||||
new EcBlocks(28, new EcBlock(1, 107), new EcBlock(5, 108)),
|
||||
new EcBlocks(28, new EcBlock(10, 46), new EcBlock(1, 47)),
|
||||
new EcBlocks(28, new EcBlock(1, 22), new EcBlock(15, 23)),
|
||||
new EcBlocks(28, new EcBlock(2, 14), new EcBlock(17, 15))
|
||||
),
|
||||
new self(
|
||||
18,
|
||||
[6, 30, 56, 82],
|
||||
new EcBlocks(30, new EcBlock(5, 120), new EcBlock(1, 121)),
|
||||
new EcBlocks(26, new EcBlock(9, 43), new EcBlock(4, 44)),
|
||||
new EcBlocks(28, new EcBlock(17, 22), new EcBlock(1, 23)),
|
||||
new EcBlocks(28, new EcBlock(2, 14), new EcBlock(19, 15))
|
||||
),
|
||||
new self(
|
||||
19,
|
||||
[6, 30, 58, 86],
|
||||
new EcBlocks(28, new EcBlock(3, 113), new EcBlock(4, 114)),
|
||||
new EcBlocks(26, new EcBlock(3, 44), new EcBlock(11, 45)),
|
||||
new EcBlocks(26, new EcBlock(17, 21), new EcBlock(4, 22)),
|
||||
new EcBlocks(26, new EcBlock(9, 13), new EcBlock(16, 14))
|
||||
),
|
||||
new self(
|
||||
20,
|
||||
[6, 34, 62, 90],
|
||||
new EcBlocks(28, new EcBlock(3, 107), new EcBlock(5, 108)),
|
||||
new EcBlocks(26, new EcBlock(3, 41), new EcBlock(13, 42)),
|
||||
new EcBlocks(30, new EcBlock(15, 24), new EcBlock(5, 25)),
|
||||
new EcBlocks(28, new EcBlock(15, 15), new EcBlock(10, 16))
|
||||
),
|
||||
new self(
|
||||
21,
|
||||
[6, 28, 50, 72, 94],
|
||||
new EcBlocks(28, new EcBlock(4, 116), new EcBlock(4, 117)),
|
||||
new EcBlocks(26, new EcBlock(17, 42)),
|
||||
new EcBlocks(28, new EcBlock(17, 22), new EcBlock(6, 23)),
|
||||
new EcBlocks(30, new EcBlock(19, 16), new EcBlock(6, 17))
|
||||
),
|
||||
new self(
|
||||
22,
|
||||
[6, 26, 50, 74, 98],
|
||||
new EcBlocks(28, new EcBlock(2, 111), new EcBlock(7, 112)),
|
||||
new EcBlocks(28, new EcBlock(17, 46)),
|
||||
new EcBlocks(30, new EcBlock(7, 24), new EcBlock(16, 25)),
|
||||
new EcBlocks(24, new EcBlock(34, 13))
|
||||
),
|
||||
new self(
|
||||
23,
|
||||
[6, 30, 54, 78, 102],
|
||||
new EcBlocks(30, new EcBlock(4, 121), new EcBlock(5, 122)),
|
||||
new EcBlocks(28, new EcBlock(4, 47), new EcBlock(14, 48)),
|
||||
new EcBlocks(30, new EcBlock(11, 24), new EcBlock(14, 25)),
|
||||
new EcBlocks(30, new EcBlock(16, 15), new EcBlock(14, 16))
|
||||
),
|
||||
new self(
|
||||
24,
|
||||
[6, 28, 54, 80, 106],
|
||||
new EcBlocks(30, new EcBlock(6, 117), new EcBlock(4, 118)),
|
||||
new EcBlocks(28, new EcBlock(6, 45), new EcBlock(14, 46)),
|
||||
new EcBlocks(30, new EcBlock(11, 24), new EcBlock(16, 25)),
|
||||
new EcBlocks(30, new EcBlock(30, 16), new EcBlock(2, 17))
|
||||
),
|
||||
new self(
|
||||
25,
|
||||
[6, 32, 58, 84, 110],
|
||||
new EcBlocks(26, new EcBlock(8, 106), new EcBlock(4, 107)),
|
||||
new EcBlocks(28, new EcBlock(8, 47), new EcBlock(13, 48)),
|
||||
new EcBlocks(30, new EcBlock(7, 24), new EcBlock(22, 25)),
|
||||
new EcBlocks(30, new EcBlock(22, 15), new EcBlock(13, 16))
|
||||
),
|
||||
new self(
|
||||
26,
|
||||
[6, 30, 58, 86, 114],
|
||||
new EcBlocks(28, new EcBlock(10, 114), new EcBlock(2, 115)),
|
||||
new EcBlocks(28, new EcBlock(19, 46), new EcBlock(4, 47)),
|
||||
new EcBlocks(28, new EcBlock(28, 22), new EcBlock(6, 23)),
|
||||
new EcBlocks(30, new EcBlock(33, 16), new EcBlock(4, 17))
|
||||
),
|
||||
new self(
|
||||
27,
|
||||
[6, 34, 62, 90, 118],
|
||||
new EcBlocks(30, new EcBlock(8, 122), new EcBlock(4, 123)),
|
||||
new EcBlocks(28, new EcBlock(22, 45), new EcBlock(3, 46)),
|
||||
new EcBlocks(30, new EcBlock(8, 23), new EcBlock(26, 24)),
|
||||
new EcBlocks(30, new EcBlock(12, 15), new EcBlock(28, 16))
|
||||
),
|
||||
new self(
|
||||
28,
|
||||
[6, 26, 50, 74, 98, 122],
|
||||
new EcBlocks(30, new EcBlock(3, 117), new EcBlock(10, 118)),
|
||||
new EcBlocks(28, new EcBlock(3, 45), new EcBlock(23, 46)),
|
||||
new EcBlocks(30, new EcBlock(4, 24), new EcBlock(31, 25)),
|
||||
new EcBlocks(30, new EcBlock(11, 15), new EcBlock(31, 16))
|
||||
),
|
||||
new self(
|
||||
29,
|
||||
[6, 30, 54, 78, 102, 126],
|
||||
new EcBlocks(30, new EcBlock(7, 116), new EcBlock(7, 117)),
|
||||
new EcBlocks(28, new EcBlock(21, 45), new EcBlock(7, 46)),
|
||||
new EcBlocks(30, new EcBlock(1, 23), new EcBlock(37, 24)),
|
||||
new EcBlocks(30, new EcBlock(19, 15), new EcBlock(26, 16))
|
||||
),
|
||||
new self(
|
||||
30,
|
||||
[6, 26, 52, 78, 104, 130],
|
||||
new EcBlocks(30, new EcBlock(5, 115), new EcBlock(10, 116)),
|
||||
new EcBlocks(28, new EcBlock(19, 47), new EcBlock(10, 48)),
|
||||
new EcBlocks(30, new EcBlock(15, 24), new EcBlock(25, 25)),
|
||||
new EcBlocks(30, new EcBlock(23, 15), new EcBlock(25, 16))
|
||||
),
|
||||
new self(
|
||||
31,
|
||||
[6, 30, 56, 82, 108, 134],
|
||||
new EcBlocks(30, new EcBlock(13, 115), new EcBlock(3, 116)),
|
||||
new EcBlocks(28, new EcBlock(2, 46), new EcBlock(29, 47)),
|
||||
new EcBlocks(30, new EcBlock(42, 24), new EcBlock(1, 25)),
|
||||
new EcBlocks(30, new EcBlock(23, 15), new EcBlock(28, 16))
|
||||
),
|
||||
new self(
|
||||
32,
|
||||
[6, 34, 60, 86, 112, 138],
|
||||
new EcBlocks(30, new EcBlock(17, 115)),
|
||||
new EcBlocks(28, new EcBlock(10, 46), new EcBlock(23, 47)),
|
||||
new EcBlocks(30, new EcBlock(10, 24), new EcBlock(35, 25)),
|
||||
new EcBlocks(30, new EcBlock(19, 15), new EcBlock(35, 16))
|
||||
),
|
||||
new self(
|
||||
33,
|
||||
[6, 30, 58, 86, 114, 142],
|
||||
new EcBlocks(30, new EcBlock(17, 115), new EcBlock(1, 116)),
|
||||
new EcBlocks(28, new EcBlock(14, 46), new EcBlock(21, 47)),
|
||||
new EcBlocks(30, new EcBlock(29, 24), new EcBlock(19, 25)),
|
||||
new EcBlocks(30, new EcBlock(11, 15), new EcBlock(46, 16))
|
||||
),
|
||||
new self(
|
||||
34,
|
||||
[6, 34, 62, 90, 118, 146],
|
||||
new EcBlocks(30, new EcBlock(13, 115), new EcBlock(6, 116)),
|
||||
new EcBlocks(28, new EcBlock(14, 46), new EcBlock(23, 47)),
|
||||
new EcBlocks(30, new EcBlock(44, 24), new EcBlock(7, 25)),
|
||||
new EcBlocks(30, new EcBlock(59, 16), new EcBlock(1, 17))
|
||||
),
|
||||
new self(
|
||||
35,
|
||||
[6, 30, 54, 78, 102, 126, 150],
|
||||
new EcBlocks(30, new EcBlock(12, 121), new EcBlock(7, 122)),
|
||||
new EcBlocks(28, new EcBlock(12, 47), new EcBlock(26, 48)),
|
||||
new EcBlocks(30, new EcBlock(39, 24), new EcBlock(14, 25)),
|
||||
new EcBlocks(30, new EcBlock(22, 15), new EcBlock(41, 16))
|
||||
),
|
||||
new self(
|
||||
36,
|
||||
[6, 24, 50, 76, 102, 128, 154],
|
||||
new EcBlocks(30, new EcBlock(6, 121), new EcBlock(14, 122)),
|
||||
new EcBlocks(28, new EcBlock(6, 47), new EcBlock(34, 48)),
|
||||
new EcBlocks(30, new EcBlock(46, 24), new EcBlock(10, 25)),
|
||||
new EcBlocks(30, new EcBlock(2, 15), new EcBlock(64, 16))
|
||||
),
|
||||
new self(
|
||||
37,
|
||||
[6, 28, 54, 80, 106, 132, 158],
|
||||
new EcBlocks(30, new EcBlock(17, 122), new EcBlock(4, 123)),
|
||||
new EcBlocks(28, new EcBlock(29, 46), new EcBlock(14, 47)),
|
||||
new EcBlocks(30, new EcBlock(49, 24), new EcBlock(10, 25)),
|
||||
new EcBlocks(30, new EcBlock(24, 15), new EcBlock(46, 16))
|
||||
),
|
||||
new self(
|
||||
38,
|
||||
[6, 32, 58, 84, 110, 136, 162],
|
||||
new EcBlocks(30, new EcBlock(4, 122), new EcBlock(18, 123)),
|
||||
new EcBlocks(28, new EcBlock(13, 46), new EcBlock(32, 47)),
|
||||
new EcBlocks(30, new EcBlock(48, 24), new EcBlock(14, 25)),
|
||||
new EcBlocks(30, new EcBlock(42, 15), new EcBlock(32, 16))
|
||||
),
|
||||
new self(
|
||||
39,
|
||||
[6, 26, 54, 82, 110, 138, 166],
|
||||
new EcBlocks(30, new EcBlock(20, 117), new EcBlock(4, 118)),
|
||||
new EcBlocks(28, new EcBlock(40, 47), new EcBlock(7, 48)),
|
||||
new EcBlocks(30, new EcBlock(43, 24), new EcBlock(22, 25)),
|
||||
new EcBlocks(30, new EcBlock(10, 15), new EcBlock(67, 16))
|
||||
),
|
||||
new self(
|
||||
40,
|
||||
[6, 30, 58, 86, 114, 142, 170],
|
||||
new EcBlocks(30, new EcBlock(19, 118), new EcBlock(6, 119)),
|
||||
new EcBlocks(28, new EcBlock(18, 47), new EcBlock(31, 48)),
|
||||
new EcBlocks(30, new EcBlock(34, 24), new EcBlock(34, 25)),
|
||||
new EcBlocks(30, new EcBlock(20, 15), new EcBlock(61, 16))
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
58
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/BlockPair.php
vendored
Normal file
58
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/BlockPair.php
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Encoder;
|
||||
|
||||
use SplFixedArray;
|
||||
|
||||
/**
|
||||
* Block pair.
|
||||
*/
|
||||
final class BlockPair
|
||||
{
|
||||
/**
|
||||
* Data bytes in the block.
|
||||
*
|
||||
* @var SplFixedArray<int>
|
||||
*/
|
||||
private $dataBytes;
|
||||
|
||||
/**
|
||||
* Error correction bytes in the block.
|
||||
*
|
||||
* @var SplFixedArray<int>
|
||||
*/
|
||||
private $errorCorrectionBytes;
|
||||
|
||||
/**
|
||||
* Creates a new block pair.
|
||||
*
|
||||
* @param SplFixedArray<int> $data
|
||||
* @param SplFixedArray<int> $errorCorrection
|
||||
*/
|
||||
public function __construct(SplFixedArray $data, SplFixedArray $errorCorrection)
|
||||
{
|
||||
$this->dataBytes = $data;
|
||||
$this->errorCorrectionBytes = $errorCorrection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data bytes.
|
||||
*
|
||||
* @return SplFixedArray<int>
|
||||
*/
|
||||
public function getDataBytes() : SplFixedArray
|
||||
{
|
||||
return $this->dataBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the error correction bytes.
|
||||
*
|
||||
* @return SplFixedArray<int>
|
||||
*/
|
||||
public function getErrorCorrectionBytes() : SplFixedArray
|
||||
{
|
||||
return $this->errorCorrectionBytes;
|
||||
}
|
||||
}
|
150
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php
vendored
Normal file
150
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/ByteMatrix.php
vendored
Normal file
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Encoder;
|
||||
|
||||
use SplFixedArray;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* Byte matrix.
|
||||
*/
|
||||
final class ByteMatrix
|
||||
{
|
||||
/**
|
||||
* Bytes in the matrix, represented as array.
|
||||
*
|
||||
* @var SplFixedArray<SplFixedArray<int>>
|
||||
*/
|
||||
private $bytes;
|
||||
|
||||
/**
|
||||
* Width of the matrix.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $width;
|
||||
|
||||
/**
|
||||
* Height of the matrix.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $height;
|
||||
|
||||
public function __construct(int $width, int $height)
|
||||
{
|
||||
$this->height = $height;
|
||||
$this->width = $width;
|
||||
$this->bytes = new SplFixedArray($height);
|
||||
|
||||
for ($y = 0; $y < $height; ++$y) {
|
||||
$this->bytes[$y] = SplFixedArray::fromArray(array_fill(0, $width, 0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of the matrix.
|
||||
*/
|
||||
public function getWidth() : int
|
||||
{
|
||||
return $this->width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the height of the matrix.
|
||||
*/
|
||||
public function getHeight() : int
|
||||
{
|
||||
return $this->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the internal representation of the matrix.
|
||||
*
|
||||
* @return SplFixedArray<SplFixedArray<int>>
|
||||
*/
|
||||
public function getArray() : SplFixedArray
|
||||
{
|
||||
return $this->bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Traversable<int>
|
||||
*/
|
||||
public function getBytes() : Traversable
|
||||
{
|
||||
foreach ($this->bytes as $row) {
|
||||
foreach ($row as $byte) {
|
||||
yield $byte;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the byte for a specific position.
|
||||
*/
|
||||
public function get(int $x, int $y) : int
|
||||
{
|
||||
return $this->bytes[$y][$x];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the byte for a specific position.
|
||||
*/
|
||||
public function set(int $x, int $y, int $value) : void
|
||||
{
|
||||
$this->bytes[$y][$x] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the matrix with a specific value.
|
||||
*/
|
||||
public function clear(int $value) : void
|
||||
{
|
||||
for ($y = 0; $y < $this->height; ++$y) {
|
||||
for ($x = 0; $x < $this->width; ++$x) {
|
||||
$this->bytes[$y][$x] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function __clone()
|
||||
{
|
||||
$this->bytes = clone $this->bytes;
|
||||
|
||||
foreach ($this->bytes as $index => $row) {
|
||||
$this->bytes[$index] = clone $row;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the matrix.
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
for ($y = 0; $y < $this->height; $y++) {
|
||||
for ($x = 0; $x < $this->width; $x++) {
|
||||
switch ($this->bytes[$y][$x]) {
|
||||
case 0:
|
||||
$result .= ' 0';
|
||||
break;
|
||||
|
||||
case 1:
|
||||
$result .= ' 1';
|
||||
break;
|
||||
|
||||
default:
|
||||
$result .= ' ';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$result .= "\n";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
668
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/Encoder.php
vendored
Normal file
668
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/Encoder.php
vendored
Normal file
|
@ -0,0 +1,668 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Encoder;
|
||||
|
||||
use BaconQrCode\Common\BitArray;
|
||||
use BaconQrCode\Common\CharacterSetEci;
|
||||
use BaconQrCode\Common\ErrorCorrectionLevel;
|
||||
use BaconQrCode\Common\Mode;
|
||||
use BaconQrCode\Common\ReedSolomonCodec;
|
||||
use BaconQrCode\Common\Version;
|
||||
use BaconQrCode\Exception\WriterException;
|
||||
use SplFixedArray;
|
||||
|
||||
/**
|
||||
* Encoder.
|
||||
*/
|
||||
final class Encoder
|
||||
{
|
||||
/**
|
||||
* Default byte encoding.
|
||||
*/
|
||||
public const DEFAULT_BYTE_MODE_ECODING = 'ISO-8859-1';
|
||||
|
||||
/**
|
||||
* The original table is defined in the table 5 of JISX0510:2004 (p.19).
|
||||
*/
|
||||
private const ALPHANUMERIC_TABLE = [
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f
|
||||
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f
|
||||
36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 0x30-0x3f
|
||||
-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f
|
||||
25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f
|
||||
];
|
||||
|
||||
/**
|
||||
* Codec cache.
|
||||
*
|
||||
* @var array<string,ReedSolomonCodec>
|
||||
*/
|
||||
private static $codecs = [];
|
||||
|
||||
/**
|
||||
* Encodes "content" with the error correction level "ecLevel".
|
||||
*/
|
||||
public static function encode(
|
||||
string $content,
|
||||
ErrorCorrectionLevel $ecLevel,
|
||||
string $encoding = self::DEFAULT_BYTE_MODE_ECODING,
|
||||
?Version $forcedVersion = null
|
||||
) : QrCode {
|
||||
// Pick an encoding mode appropriate for the content. Note that this
|
||||
// will not attempt to use multiple modes / segments even if that were
|
||||
// more efficient. Would be nice.
|
||||
$mode = self::chooseMode($content, $encoding);
|
||||
|
||||
// This will store the header information, like mode and length, as well
|
||||
// as "header" segments like an ECI segment.
|
||||
$headerBits = new BitArray();
|
||||
|
||||
// Append ECI segment if applicable
|
||||
if (Mode::BYTE() === $mode && self::DEFAULT_BYTE_MODE_ECODING !== $encoding) {
|
||||
$eci = CharacterSetEci::getCharacterSetEciByName($encoding);
|
||||
|
||||
if (null !== $eci) {
|
||||
self::appendEci($eci, $headerBits);
|
||||
}
|
||||
}
|
||||
|
||||
// (With ECI in place,) Write the mode marker
|
||||
self::appendModeInfo($mode, $headerBits);
|
||||
|
||||
// Collect data within the main segment, separately, to count its size
|
||||
// if needed. Don't add it to main payload yet.
|
||||
$dataBits = new BitArray();
|
||||
self::appendBytes($content, $mode, $dataBits, $encoding);
|
||||
|
||||
// Hard part: need to know version to know how many bits length takes.
|
||||
// But need to know how many bits it takes to know version. First we
|
||||
// take a guess at version by assuming version will be the minimum, 1:
|
||||
$provisionalBitsNeeded = $headerBits->getSize()
|
||||
+ $mode->getCharacterCountBits(Version::getVersionForNumber(1))
|
||||
+ $dataBits->getSize();
|
||||
$provisionalVersion = self::chooseVersion($provisionalBitsNeeded, $ecLevel);
|
||||
|
||||
// Use that guess to calculate the right version. I am still not sure
|
||||
// this works in 100% of cases.
|
||||
$bitsNeeded = $headerBits->getSize()
|
||||
+ $mode->getCharacterCountBits($provisionalVersion)
|
||||
+ $dataBits->getSize();
|
||||
$version = self::chooseVersion($bitsNeeded, $ecLevel);
|
||||
|
||||
if (null !== $forcedVersion) {
|
||||
// Forced version check
|
||||
if ($version->getVersionNumber() <= $forcedVersion->getVersionNumber()) {
|
||||
// Calculated minimum version is same or equal as forced version
|
||||
$version = $forcedVersion;
|
||||
} else {
|
||||
throw new WriterException(
|
||||
'Invalid version! Calculated version: '
|
||||
. $version->getVersionNumber()
|
||||
. ', requested version: '
|
||||
. $forcedVersion->getVersionNumber()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$headerAndDataBits = new BitArray();
|
||||
$headerAndDataBits->appendBitArray($headerBits);
|
||||
|
||||
// Find "length" of main segment and write it.
|
||||
$numLetters = (Mode::BYTE() === $mode ? $dataBits->getSizeInBytes() : strlen($content));
|
||||
self::appendLengthInfo($numLetters, $version, $mode, $headerAndDataBits);
|
||||
|
||||
// Put data together into the overall payload.
|
||||
$headerAndDataBits->appendBitArray($dataBits);
|
||||
$ecBlocks = $version->getEcBlocksForLevel($ecLevel);
|
||||
$numDataBytes = $version->getTotalCodewords() - $ecBlocks->getTotalEcCodewords();
|
||||
|
||||
// Terminate the bits properly.
|
||||
self::terminateBits($numDataBytes, $headerAndDataBits);
|
||||
|
||||
// Interleave data bits with error correction code.
|
||||
$finalBits = self::interleaveWithEcBytes(
|
||||
$headerAndDataBits,
|
||||
$version->getTotalCodewords(),
|
||||
$numDataBytes,
|
||||
$ecBlocks->getNumBlocks()
|
||||
);
|
||||
|
||||
// Choose the mask pattern.
|
||||
$dimension = $version->getDimensionForVersion();
|
||||
$matrix = new ByteMatrix($dimension, $dimension);
|
||||
$maskPattern = self::chooseMaskPattern($finalBits, $ecLevel, $version, $matrix);
|
||||
|
||||
// Build the matrix.
|
||||
MatrixUtil::buildMatrix($finalBits, $ecLevel, $version, $maskPattern, $matrix);
|
||||
|
||||
return new QrCode($mode, $ecLevel, $version, $maskPattern, $matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the alphanumeric code for a byte.
|
||||
*/
|
||||
private static function getAlphanumericCode(int $code) : int
|
||||
{
|
||||
if (isset(self::ALPHANUMERIC_TABLE[$code])) {
|
||||
return self::ALPHANUMERIC_TABLE[$code];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chooses the best mode for a given content.
|
||||
*/
|
||||
private static function chooseMode(string $content, string $encoding = null) : Mode
|
||||
{
|
||||
if (null !== $encoding && 0 === strcasecmp($encoding, 'SHIFT-JIS')) {
|
||||
return self::isOnlyDoubleByteKanji($content) ? Mode::KANJI() : Mode::BYTE();
|
||||
}
|
||||
|
||||
$hasNumeric = false;
|
||||
$hasAlphanumeric = false;
|
||||
$contentLength = strlen($content);
|
||||
|
||||
for ($i = 0; $i < $contentLength; ++$i) {
|
||||
$char = $content[$i];
|
||||
|
||||
if (ctype_digit($char)) {
|
||||
$hasNumeric = true;
|
||||
} elseif (-1 !== self::getAlphanumericCode(ord($char))) {
|
||||
$hasAlphanumeric = true;
|
||||
} else {
|
||||
return Mode::BYTE();
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasAlphanumeric) {
|
||||
return Mode::ALPHANUMERIC();
|
||||
} elseif ($hasNumeric) {
|
||||
return Mode::NUMERIC();
|
||||
}
|
||||
|
||||
return Mode::BYTE();
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the mask penalty for a matrix.
|
||||
*/
|
||||
private static function calculateMaskPenalty(ByteMatrix $matrix) : int
|
||||
{
|
||||
return (
|
||||
MaskUtil::applyMaskPenaltyRule1($matrix)
|
||||
+ MaskUtil::applyMaskPenaltyRule2($matrix)
|
||||
+ MaskUtil::applyMaskPenaltyRule3($matrix)
|
||||
+ MaskUtil::applyMaskPenaltyRule4($matrix)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if content only consists of double-byte kanji characters.
|
||||
*/
|
||||
private static function isOnlyDoubleByteKanji(string $content) : bool
|
||||
{
|
||||
$bytes = @iconv('utf-8', 'SHIFT-JIS', $content);
|
||||
|
||||
if (false === $bytes) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$length = strlen($bytes);
|
||||
|
||||
if (0 !== $length % 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $length; $i += 2) {
|
||||
$byte = $bytes[$i] & 0xff;
|
||||
|
||||
if (($byte < 0x81 || $byte > 0x9f) && $byte < 0xe0 || $byte > 0xeb) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chooses the best mask pattern for a matrix.
|
||||
*/
|
||||
private static function chooseMaskPattern(
|
||||
BitArray $bits,
|
||||
ErrorCorrectionLevel $ecLevel,
|
||||
Version $version,
|
||||
ByteMatrix $matrix
|
||||
) : int {
|
||||
$minPenalty = PHP_INT_MAX;
|
||||
$bestMaskPattern = -1;
|
||||
|
||||
for ($maskPattern = 0; $maskPattern < QrCode::NUM_MASK_PATTERNS; ++$maskPattern) {
|
||||
MatrixUtil::buildMatrix($bits, $ecLevel, $version, $maskPattern, $matrix);
|
||||
$penalty = self::calculateMaskPenalty($matrix);
|
||||
|
||||
if ($penalty < $minPenalty) {
|
||||
$minPenalty = $penalty;
|
||||
$bestMaskPattern = $maskPattern;
|
||||
}
|
||||
}
|
||||
|
||||
return $bestMaskPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Chooses the best version for the input.
|
||||
*
|
||||
* @throws WriterException if data is too big
|
||||
*/
|
||||
private static function chooseVersion(int $numInputBits, ErrorCorrectionLevel $ecLevel) : Version
|
||||
{
|
||||
for ($versionNum = 1; $versionNum <= 40; ++$versionNum) {
|
||||
$version = Version::getVersionForNumber($versionNum);
|
||||
$numBytes = $version->getTotalCodewords();
|
||||
|
||||
$ecBlocks = $version->getEcBlocksForLevel($ecLevel);
|
||||
$numEcBytes = $ecBlocks->getTotalEcCodewords();
|
||||
|
||||
$numDataBytes = $numBytes - $numEcBytes;
|
||||
$totalInputBytes = intdiv($numInputBits + 8, 8);
|
||||
|
||||
if ($numDataBytes >= $totalInputBytes) {
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
|
||||
throw new WriterException('Data too big');
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminates the bits in a bit array.
|
||||
*
|
||||
* @throws WriterException if data bits cannot fit in the QR code
|
||||
* @throws WriterException if bits size does not equal the capacity
|
||||
*/
|
||||
private static function terminateBits(int $numDataBytes, BitArray $bits) : void
|
||||
{
|
||||
$capacity = $numDataBytes << 3;
|
||||
|
||||
if ($bits->getSize() > $capacity) {
|
||||
throw new WriterException('Data bits cannot fit in the QR code');
|
||||
}
|
||||
|
||||
for ($i = 0; $i < 4 && $bits->getSize() < $capacity; ++$i) {
|
||||
$bits->appendBit(false);
|
||||
}
|
||||
|
||||
$numBitsInLastByte = $bits->getSize() & 0x7;
|
||||
|
||||
if ($numBitsInLastByte > 0) {
|
||||
for ($i = $numBitsInLastByte; $i < 8; ++$i) {
|
||||
$bits->appendBit(false);
|
||||
}
|
||||
}
|
||||
|
||||
$numPaddingBytes = $numDataBytes - $bits->getSizeInBytes();
|
||||
|
||||
for ($i = 0; $i < $numPaddingBytes; ++$i) {
|
||||
$bits->appendBits(0 === ($i & 0x1) ? 0xec : 0x11, 8);
|
||||
}
|
||||
|
||||
if ($bits->getSize() !== $capacity) {
|
||||
throw new WriterException('Bits size does not equal capacity');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets number of data- and EC bytes for a block ID.
|
||||
*
|
||||
* @return int[]
|
||||
* @throws WriterException if block ID is too large
|
||||
* @throws WriterException if EC bytes mismatch
|
||||
* @throws WriterException if RS blocks mismatch
|
||||
* @throws WriterException if total bytes mismatch
|
||||
*/
|
||||
private static function getNumDataBytesAndNumEcBytesForBlockId(
|
||||
int $numTotalBytes,
|
||||
int $numDataBytes,
|
||||
int $numRsBlocks,
|
||||
int $blockId
|
||||
) : array {
|
||||
if ($blockId >= $numRsBlocks) {
|
||||
throw new WriterException('Block ID too large');
|
||||
}
|
||||
|
||||
$numRsBlocksInGroup2 = $numTotalBytes % $numRsBlocks;
|
||||
$numRsBlocksInGroup1 = $numRsBlocks - $numRsBlocksInGroup2;
|
||||
$numTotalBytesInGroup1 = intdiv($numTotalBytes, $numRsBlocks);
|
||||
$numTotalBytesInGroup2 = $numTotalBytesInGroup1 + 1;
|
||||
$numDataBytesInGroup1 = intdiv($numDataBytes, $numRsBlocks);
|
||||
$numDataBytesInGroup2 = $numDataBytesInGroup1 + 1;
|
||||
$numEcBytesInGroup1 = $numTotalBytesInGroup1 - $numDataBytesInGroup1;
|
||||
$numEcBytesInGroup2 = $numTotalBytesInGroup2 - $numDataBytesInGroup2;
|
||||
|
||||
if ($numEcBytesInGroup1 !== $numEcBytesInGroup2) {
|
||||
throw new WriterException('EC bytes mismatch');
|
||||
}
|
||||
|
||||
if ($numRsBlocks !== $numRsBlocksInGroup1 + $numRsBlocksInGroup2) {
|
||||
throw new WriterException('RS blocks mismatch');
|
||||
}
|
||||
|
||||
if ($numTotalBytes !==
|
||||
(($numDataBytesInGroup1 + $numEcBytesInGroup1) * $numRsBlocksInGroup1)
|
||||
+ (($numDataBytesInGroup2 + $numEcBytesInGroup2) * $numRsBlocksInGroup2)
|
||||
) {
|
||||
throw new WriterException('Total bytes mismatch');
|
||||
}
|
||||
|
||||
if ($blockId < $numRsBlocksInGroup1) {
|
||||
return [$numDataBytesInGroup1, $numEcBytesInGroup1];
|
||||
} else {
|
||||
return [$numDataBytesInGroup2, $numEcBytesInGroup2];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interleaves data with EC bytes.
|
||||
*
|
||||
* @throws WriterException if number of bits and data bytes does not match
|
||||
* @throws WriterException if data bytes does not match offset
|
||||
* @throws WriterException if an interleaving error occurs
|
||||
*/
|
||||
private static function interleaveWithEcBytes(
|
||||
BitArray $bits,
|
||||
int $numTotalBytes,
|
||||
int $numDataBytes,
|
||||
int $numRsBlocks
|
||||
) : BitArray {
|
||||
if ($bits->getSizeInBytes() !== $numDataBytes) {
|
||||
throw new WriterException('Number of bits and data bytes does not match');
|
||||
}
|
||||
|
||||
$dataBytesOffset = 0;
|
||||
$maxNumDataBytes = 0;
|
||||
$maxNumEcBytes = 0;
|
||||
|
||||
$blocks = new SplFixedArray($numRsBlocks);
|
||||
|
||||
for ($i = 0; $i < $numRsBlocks; ++$i) {
|
||||
list($numDataBytesInBlock, $numEcBytesInBlock) = self::getNumDataBytesAndNumEcBytesForBlockId(
|
||||
$numTotalBytes,
|
||||
$numDataBytes,
|
||||
$numRsBlocks,
|
||||
$i
|
||||
);
|
||||
|
||||
$size = $numDataBytesInBlock;
|
||||
$dataBytes = $bits->toBytes(8 * $dataBytesOffset, $size);
|
||||
$ecBytes = self::generateEcBytes($dataBytes, $numEcBytesInBlock);
|
||||
$blocks[$i] = new BlockPair($dataBytes, $ecBytes);
|
||||
|
||||
$maxNumDataBytes = max($maxNumDataBytes, $size);
|
||||
$maxNumEcBytes = max($maxNumEcBytes, count($ecBytes));
|
||||
$dataBytesOffset += $numDataBytesInBlock;
|
||||
}
|
||||
|
||||
if ($numDataBytes !== $dataBytesOffset) {
|
||||
throw new WriterException('Data bytes does not match offset');
|
||||
}
|
||||
|
||||
$result = new BitArray();
|
||||
|
||||
for ($i = 0; $i < $maxNumDataBytes; ++$i) {
|
||||
foreach ($blocks as $block) {
|
||||
$dataBytes = $block->getDataBytes();
|
||||
|
||||
if ($i < count($dataBytes)) {
|
||||
$result->appendBits($dataBytes[$i], 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $maxNumEcBytes; ++$i) {
|
||||
foreach ($blocks as $block) {
|
||||
$ecBytes = $block->getErrorCorrectionBytes();
|
||||
|
||||
if ($i < count($ecBytes)) {
|
||||
$result->appendBits($ecBytes[$i], 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($numTotalBytes !== $result->getSizeInBytes()) {
|
||||
throw new WriterException(
|
||||
'Interleaving error: ' . $numTotalBytes . ' and ' . $result->getSizeInBytes() . ' differ'
|
||||
);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates EC bytes for given data.
|
||||
*
|
||||
* @param SplFixedArray<int> $dataBytes
|
||||
* @return SplFixedArray<int>
|
||||
*/
|
||||
private static function generateEcBytes(SplFixedArray $dataBytes, int $numEcBytesInBlock) : SplFixedArray
|
||||
{
|
||||
$numDataBytes = count($dataBytes);
|
||||
$toEncode = new SplFixedArray($numDataBytes + $numEcBytesInBlock);
|
||||
|
||||
for ($i = 0; $i < $numDataBytes; $i++) {
|
||||
$toEncode[$i] = $dataBytes[$i] & 0xff;
|
||||
}
|
||||
|
||||
$ecBytes = new SplFixedArray($numEcBytesInBlock);
|
||||
$codec = self::getCodec($numDataBytes, $numEcBytesInBlock);
|
||||
$codec->encode($toEncode, $ecBytes);
|
||||
|
||||
return $ecBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an RS codec and caches it.
|
||||
*/
|
||||
private static function getCodec(int $numDataBytes, int $numEcBytesInBlock) : ReedSolomonCodec
|
||||
{
|
||||
$cacheId = $numDataBytes . '-' . $numEcBytesInBlock;
|
||||
|
||||
if (isset(self::$codecs[$cacheId])) {
|
||||
return self::$codecs[$cacheId];
|
||||
}
|
||||
|
||||
return self::$codecs[$cacheId] = new ReedSolomonCodec(
|
||||
8,
|
||||
0x11d,
|
||||
0,
|
||||
1,
|
||||
$numEcBytesInBlock,
|
||||
255 - $numDataBytes - $numEcBytesInBlock
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends mode information to a bit array.
|
||||
*/
|
||||
private static function appendModeInfo(Mode $mode, BitArray $bits) : void
|
||||
{
|
||||
$bits->appendBits($mode->getBits(), 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends length information to a bit array.
|
||||
*
|
||||
* @throws WriterException if num letters is bigger than expected
|
||||
*/
|
||||
private static function appendLengthInfo(int $numLetters, Version $version, Mode $mode, BitArray $bits) : void
|
||||
{
|
||||
$numBits = $mode->getCharacterCountBits($version);
|
||||
|
||||
if ($numLetters >= (1 << $numBits)) {
|
||||
throw new WriterException($numLetters . ' is bigger than ' . ((1 << $numBits) - 1));
|
||||
}
|
||||
|
||||
$bits->appendBits($numLetters, $numBits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends bytes to a bit array in a specific mode.
|
||||
*
|
||||
* @throws WriterException if an invalid mode was supplied
|
||||
*/
|
||||
private static function appendBytes(string $content, Mode $mode, BitArray $bits, string $encoding) : void
|
||||
{
|
||||
switch ($mode) {
|
||||
case Mode::NUMERIC():
|
||||
self::appendNumericBytes($content, $bits);
|
||||
break;
|
||||
|
||||
case Mode::ALPHANUMERIC():
|
||||
self::appendAlphanumericBytes($content, $bits);
|
||||
break;
|
||||
|
||||
case Mode::BYTE():
|
||||
self::append8BitBytes($content, $bits, $encoding);
|
||||
break;
|
||||
|
||||
case Mode::KANJI():
|
||||
self::appendKanjiBytes($content, $bits);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new WriterException('Invalid mode: ' . $mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends numeric bytes to a bit array.
|
||||
*/
|
||||
private static function appendNumericBytes(string $content, BitArray $bits) : void
|
||||
{
|
||||
$length = strlen($content);
|
||||
$i = 0;
|
||||
|
||||
while ($i < $length) {
|
||||
$num1 = (int) $content[$i];
|
||||
|
||||
if ($i + 2 < $length) {
|
||||
// Encode three numeric letters in ten bits.
|
||||
$num2 = (int) $content[$i + 1];
|
||||
$num3 = (int) $content[$i + 2];
|
||||
$bits->appendBits($num1 * 100 + $num2 * 10 + $num3, 10);
|
||||
$i += 3;
|
||||
} elseif ($i + 1 < $length) {
|
||||
// Encode two numeric letters in seven bits.
|
||||
$num2 = (int) $content[$i + 1];
|
||||
$bits->appendBits($num1 * 10 + $num2, 7);
|
||||
$i += 2;
|
||||
} else {
|
||||
// Encode one numeric letter in four bits.
|
||||
$bits->appendBits($num1, 4);
|
||||
++$i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends alpha-numeric bytes to a bit array.
|
||||
*
|
||||
* @throws WriterException if an invalid alphanumeric code was found
|
||||
*/
|
||||
private static function appendAlphanumericBytes(string $content, BitArray $bits) : void
|
||||
{
|
||||
$length = strlen($content);
|
||||
$i = 0;
|
||||
|
||||
while ($i < $length) {
|
||||
$code1 = self::getAlphanumericCode(ord($content[$i]));
|
||||
|
||||
if (-1 === $code1) {
|
||||
throw new WriterException('Invalid alphanumeric code');
|
||||
}
|
||||
|
||||
if ($i + 1 < $length) {
|
||||
$code2 = self::getAlphanumericCode(ord($content[$i + 1]));
|
||||
|
||||
if (-1 === $code2) {
|
||||
throw new WriterException('Invalid alphanumeric code');
|
||||
}
|
||||
|
||||
// Encode two alphanumeric letters in 11 bits.
|
||||
$bits->appendBits($code1 * 45 + $code2, 11);
|
||||
$i += 2;
|
||||
} else {
|
||||
// Encode one alphanumeric letter in six bits.
|
||||
$bits->appendBits($code1, 6);
|
||||
++$i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends regular 8-bit bytes to a bit array.
|
||||
*
|
||||
* @throws WriterException if content cannot be encoded to target encoding
|
||||
*/
|
||||
private static function append8BitBytes(string $content, BitArray $bits, string $encoding) : void
|
||||
{
|
||||
$bytes = @iconv('utf-8', $encoding, $content);
|
||||
|
||||
if (false === $bytes) {
|
||||
throw new WriterException('Could not encode content to ' . $encoding);
|
||||
}
|
||||
|
||||
$length = strlen($bytes);
|
||||
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$bits->appendBits(ord($bytes[$i]), 8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends KANJI bytes to a bit array.
|
||||
*
|
||||
* @throws WriterException if content does not seem to be encoded in SHIFT-JIS
|
||||
* @throws WriterException if an invalid byte sequence occurs
|
||||
*/
|
||||
private static function appendKanjiBytes(string $content, BitArray $bits) : void
|
||||
{
|
||||
if (strlen($content) % 2 > 0) {
|
||||
// We just do a simple length check here. The for loop will check
|
||||
// individual characters.
|
||||
throw new WriterException('Content does not seem to be encoded in SHIFT-JIS');
|
||||
}
|
||||
|
||||
$length = strlen($content);
|
||||
|
||||
for ($i = 0; $i < $length; $i += 2) {
|
||||
$byte1 = ord($content[$i]) & 0xff;
|
||||
$byte2 = ord($content[$i + 1]) & 0xff;
|
||||
$code = ($byte1 << 8) | $byte2;
|
||||
|
||||
if ($code >= 0x8140 && $code <= 0x9ffc) {
|
||||
$subtracted = $code - 0x8140;
|
||||
} elseif ($code >= 0xe040 && $code <= 0xebbf) {
|
||||
$subtracted = $code - 0xc140;
|
||||
} else {
|
||||
throw new WriterException('Invalid byte sequence');
|
||||
}
|
||||
|
||||
$encoded = (($subtracted >> 8) * 0xc0) + ($subtracted & 0xff);
|
||||
|
||||
$bits->appendBits($encoded, 13);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends ECI information to a bit array.
|
||||
*/
|
||||
private static function appendEci(CharacterSetEci $eci, BitArray $bits) : void
|
||||
{
|
||||
$mode = Mode::ECI();
|
||||
$bits->appendBits($mode->getBits(), 4);
|
||||
$bits->appendBits($eci->getValue(), 8);
|
||||
}
|
||||
}
|
271
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/MaskUtil.php
vendored
Normal file
271
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/MaskUtil.php
vendored
Normal file
|
@ -0,0 +1,271 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Encoder;
|
||||
|
||||
use BaconQrCode\Common\BitUtils;
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* Mask utility.
|
||||
*/
|
||||
final class MaskUtil
|
||||
{
|
||||
/**#@+
|
||||
* Penalty weights from section 6.8.2.1
|
||||
*/
|
||||
const N1 = 3;
|
||||
const N2 = 3;
|
||||
const N3 = 40;
|
||||
const N4 = 10;
|
||||
/**#@-*/
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies mask penalty rule 1 and returns the penalty.
|
||||
*
|
||||
* Finds repetitive cells with the same color and gives penalty to them.
|
||||
* Example: 00000 or 11111.
|
||||
*/
|
||||
public static function applyMaskPenaltyRule1(ByteMatrix $matrix) : int
|
||||
{
|
||||
return (
|
||||
self::applyMaskPenaltyRule1Internal($matrix, true)
|
||||
+ self::applyMaskPenaltyRule1Internal($matrix, false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies mask penalty rule 2 and returns the penalty.
|
||||
*
|
||||
* Finds 2x2 blocks with the same color and gives penalty to them. This is
|
||||
* actually equivalent to the spec's rule, which is to find MxN blocks and
|
||||
* give a penalty proportional to (M-1)x(N-1), because this is the number of
|
||||
* 2x2 blocks inside such a block.
|
||||
*/
|
||||
public static function applyMaskPenaltyRule2(ByteMatrix $matrix) : int
|
||||
{
|
||||
$penalty = 0;
|
||||
$array = $matrix->getArray();
|
||||
$width = $matrix->getWidth();
|
||||
$height = $matrix->getHeight();
|
||||
|
||||
for ($y = 0; $y < $height - 1; ++$y) {
|
||||
for ($x = 0; $x < $width - 1; ++$x) {
|
||||
$value = $array[$y][$x];
|
||||
|
||||
if ($value === $array[$y][$x + 1]
|
||||
&& $value === $array[$y + 1][$x]
|
||||
&& $value === $array[$y + 1][$x + 1]
|
||||
) {
|
||||
++$penalty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return self::N2 * $penalty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies mask penalty rule 3 and returns the penalty.
|
||||
*
|
||||
* Finds consecutive cells of 00001011101 or 10111010000, and gives penalty
|
||||
* to them. If we find patterns like 000010111010000, we give penalties
|
||||
* twice (i.e. 40 * 2).
|
||||
*/
|
||||
public static function applyMaskPenaltyRule3(ByteMatrix $matrix) : int
|
||||
{
|
||||
$penalty = 0;
|
||||
$array = $matrix->getArray();
|
||||
$width = $matrix->getWidth();
|
||||
$height = $matrix->getHeight();
|
||||
|
||||
for ($y = 0; $y < $height; ++$y) {
|
||||
for ($x = 0; $x < $width; ++$x) {
|
||||
if ($x + 6 < $width
|
||||
&& 1 === $array[$y][$x]
|
||||
&& 0 === $array[$y][$x + 1]
|
||||
&& 1 === $array[$y][$x + 2]
|
||||
&& 1 === $array[$y][$x + 3]
|
||||
&& 1 === $array[$y][$x + 4]
|
||||
&& 0 === $array[$y][$x + 5]
|
||||
&& 1 === $array[$y][$x + 6]
|
||||
&& (
|
||||
(
|
||||
$x + 10 < $width
|
||||
&& 0 === $array[$y][$x + 7]
|
||||
&& 0 === $array[$y][$x + 8]
|
||||
&& 0 === $array[$y][$x + 9]
|
||||
&& 0 === $array[$y][$x + 10]
|
||||
)
|
||||
|| (
|
||||
$x - 4 >= 0
|
||||
&& 0 === $array[$y][$x - 1]
|
||||
&& 0 === $array[$y][$x - 2]
|
||||
&& 0 === $array[$y][$x - 3]
|
||||
&& 0 === $array[$y][$x - 4]
|
||||
)
|
||||
)
|
||||
) {
|
||||
$penalty += self::N3;
|
||||
}
|
||||
|
||||
if ($y + 6 < $height
|
||||
&& 1 === $array[$y][$x]
|
||||
&& 0 === $array[$y + 1][$x]
|
||||
&& 1 === $array[$y + 2][$x]
|
||||
&& 1 === $array[$y + 3][$x]
|
||||
&& 1 === $array[$y + 4][$x]
|
||||
&& 0 === $array[$y + 5][$x]
|
||||
&& 1 === $array[$y + 6][$x]
|
||||
&& (
|
||||
(
|
||||
$y + 10 < $height
|
||||
&& 0 === $array[$y + 7][$x]
|
||||
&& 0 === $array[$y + 8][$x]
|
||||
&& 0 === $array[$y + 9][$x]
|
||||
&& 0 === $array[$y + 10][$x]
|
||||
)
|
||||
|| (
|
||||
$y - 4 >= 0
|
||||
&& 0 === $array[$y - 1][$x]
|
||||
&& 0 === $array[$y - 2][$x]
|
||||
&& 0 === $array[$y - 3][$x]
|
||||
&& 0 === $array[$y - 4][$x]
|
||||
)
|
||||
)
|
||||
) {
|
||||
$penalty += self::N3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $penalty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies mask penalty rule 4 and returns the penalty.
|
||||
*
|
||||
* Calculates the ratio of dark cells and gives penalty if the ratio is far
|
||||
* from 50%. It gives 10 penalty for 5% distance.
|
||||
*/
|
||||
public static function applyMaskPenaltyRule4(ByteMatrix $matrix) : int
|
||||
{
|
||||
$numDarkCells = 0;
|
||||
|
||||
$array = $matrix->getArray();
|
||||
$width = $matrix->getWidth();
|
||||
$height = $matrix->getHeight();
|
||||
|
||||
for ($y = 0; $y < $height; ++$y) {
|
||||
$arrayY = $array[$y];
|
||||
|
||||
for ($x = 0; $x < $width; ++$x) {
|
||||
if (1 === $arrayY[$x]) {
|
||||
++$numDarkCells;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$numTotalCells = $height * $width;
|
||||
$darkRatio = $numDarkCells / $numTotalCells;
|
||||
$fixedPercentVariances = (int) (abs($darkRatio - 0.5) * 20);
|
||||
|
||||
return $fixedPercentVariances * self::N4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mask bit for "getMaskPattern" at "x" and "y".
|
||||
*
|
||||
* See 8.8 of JISX0510:2004 for mask pattern conditions.
|
||||
*
|
||||
* @throws InvalidArgumentException if an invalid mask pattern was supplied
|
||||
*/
|
||||
public static function getDataMaskBit(int $maskPattern, int $x, int $y) : bool
|
||||
{
|
||||
switch ($maskPattern) {
|
||||
case 0:
|
||||
$intermediate = ($y + $x) & 0x1;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
$intermediate = $y & 0x1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
$intermediate = $x % 3;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
$intermediate = ($y + $x) % 3;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
$intermediate = (BitUtils::unsignedRightShift($y, 1) + (int) ($x / 3)) & 0x1;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
$temp = $y * $x;
|
||||
$intermediate = ($temp & 0x1) + ($temp % 3);
|
||||
break;
|
||||
|
||||
case 6:
|
||||
$temp = $y * $x;
|
||||
$intermediate = (($temp & 0x1) + ($temp % 3)) & 0x1;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
$temp = $y * $x;
|
||||
$intermediate = (($temp % 3) + (($y + $x) & 0x1)) & 0x1;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new InvalidArgumentException('Invalid mask pattern: ' . $maskPattern);
|
||||
}
|
||||
|
||||
return 0 == $intermediate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for applyMaskPenaltyRule1.
|
||||
*
|
||||
* We need this for doing this calculation in both vertical and horizontal
|
||||
* orders respectively.
|
||||
*/
|
||||
private static function applyMaskPenaltyRule1Internal(ByteMatrix $matrix, bool $isHorizontal) : int
|
||||
{
|
||||
$penalty = 0;
|
||||
$iLimit = $isHorizontal ? $matrix->getHeight() : $matrix->getWidth();
|
||||
$jLimit = $isHorizontal ? $matrix->getWidth() : $matrix->getHeight();
|
||||
$array = $matrix->getArray();
|
||||
|
||||
for ($i = 0; $i < $iLimit; ++$i) {
|
||||
$numSameBitCells = 0;
|
||||
$prevBit = -1;
|
||||
|
||||
for ($j = 0; $j < $jLimit; $j++) {
|
||||
$bit = $isHorizontal ? $array[$i][$j] : $array[$j][$i];
|
||||
|
||||
if ($bit === $prevBit) {
|
||||
++$numSameBitCells;
|
||||
} else {
|
||||
if ($numSameBitCells >= 5) {
|
||||
$penalty += self::N1 + ($numSameBitCells - 5);
|
||||
}
|
||||
|
||||
$numSameBitCells = 1;
|
||||
$prevBit = $bit;
|
||||
}
|
||||
}
|
||||
|
||||
if ($numSameBitCells >= 5) {
|
||||
$penalty += self::N1 + ($numSameBitCells - 5);
|
||||
}
|
||||
}
|
||||
|
||||
return $penalty;
|
||||
}
|
||||
}
|
513
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php
vendored
Normal file
513
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/MatrixUtil.php
vendored
Normal file
|
@ -0,0 +1,513 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Encoder;
|
||||
|
||||
use BaconQrCode\Common\BitArray;
|
||||
use BaconQrCode\Common\ErrorCorrectionLevel;
|
||||
use BaconQrCode\Common\Version;
|
||||
use BaconQrCode\Exception\RuntimeException;
|
||||
use BaconQrCode\Exception\WriterException;
|
||||
|
||||
/**
|
||||
* Matrix utility.
|
||||
*/
|
||||
final class MatrixUtil
|
||||
{
|
||||
/**
|
||||
* Position detection pattern.
|
||||
*/
|
||||
private const POSITION_DETECTION_PATTERN = [
|
||||
[1, 1, 1, 1, 1, 1, 1],
|
||||
[1, 0, 0, 0, 0, 0, 1],
|
||||
[1, 0, 1, 1, 1, 0, 1],
|
||||
[1, 0, 1, 1, 1, 0, 1],
|
||||
[1, 0, 1, 1, 1, 0, 1],
|
||||
[1, 0, 0, 0, 0, 0, 1],
|
||||
[1, 1, 1, 1, 1, 1, 1],
|
||||
];
|
||||
|
||||
/**
|
||||
* Position adjustment pattern.
|
||||
*/
|
||||
private const POSITION_ADJUSTMENT_PATTERN = [
|
||||
[1, 1, 1, 1, 1],
|
||||
[1, 0, 0, 0, 1],
|
||||
[1, 0, 1, 0, 1],
|
||||
[1, 0, 0, 0, 1],
|
||||
[1, 1, 1, 1, 1],
|
||||
];
|
||||
|
||||
/**
|
||||
* Coordinates for position adjustment patterns for each version.
|
||||
*/
|
||||
private const POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE = [
|
||||
[null, null, null, null, null, null, null], // Version 1
|
||||
[ 6, 18, null, null, null, null, null], // Version 2
|
||||
[ 6, 22, null, null, null, null, null], // Version 3
|
||||
[ 6, 26, null, null, null, null, null], // Version 4
|
||||
[ 6, 30, null, null, null, null, null], // Version 5
|
||||
[ 6, 34, null, null, null, null, null], // Version 6
|
||||
[ 6, 22, 38, null, null, null, null], // Version 7
|
||||
[ 6, 24, 42, null, null, null, null], // Version 8
|
||||
[ 6, 26, 46, null, null, null, null], // Version 9
|
||||
[ 6, 28, 50, null, null, null, null], // Version 10
|
||||
[ 6, 30, 54, null, null, null, null], // Version 11
|
||||
[ 6, 32, 58, null, null, null, null], // Version 12
|
||||
[ 6, 34, 62, null, null, null, null], // Version 13
|
||||
[ 6, 26, 46, 66, null, null, null], // Version 14
|
||||
[ 6, 26, 48, 70, null, null, null], // Version 15
|
||||
[ 6, 26, 50, 74, null, null, null], // Version 16
|
||||
[ 6, 30, 54, 78, null, null, null], // Version 17
|
||||
[ 6, 30, 56, 82, null, null, null], // Version 18
|
||||
[ 6, 30, 58, 86, null, null, null], // Version 19
|
||||
[ 6, 34, 62, 90, null, null, null], // Version 20
|
||||
[ 6, 28, 50, 72, 94, null, null], // Version 21
|
||||
[ 6, 26, 50, 74, 98, null, null], // Version 22
|
||||
[ 6, 30, 54, 78, 102, null, null], // Version 23
|
||||
[ 6, 28, 54, 80, 106, null, null], // Version 24
|
||||
[ 6, 32, 58, 84, 110, null, null], // Version 25
|
||||
[ 6, 30, 58, 86, 114, null, null], // Version 26
|
||||
[ 6, 34, 62, 90, 118, null, null], // Version 27
|
||||
[ 6, 26, 50, 74, 98, 122, null], // Version 28
|
||||
[ 6, 30, 54, 78, 102, 126, null], // Version 29
|
||||
[ 6, 26, 52, 78, 104, 130, null], // Version 30
|
||||
[ 6, 30, 56, 82, 108, 134, null], // Version 31
|
||||
[ 6, 34, 60, 86, 112, 138, null], // Version 32
|
||||
[ 6, 30, 58, 86, 114, 142, null], // Version 33
|
||||
[ 6, 34, 62, 90, 118, 146, null], // Version 34
|
||||
[ 6, 30, 54, 78, 102, 126, 150], // Version 35
|
||||
[ 6, 24, 50, 76, 102, 128, 154], // Version 36
|
||||
[ 6, 28, 54, 80, 106, 132, 158], // Version 37
|
||||
[ 6, 32, 58, 84, 110, 136, 162], // Version 38
|
||||
[ 6, 26, 54, 82, 110, 138, 166], // Version 39
|
||||
[ 6, 30, 58, 86, 114, 142, 170], // Version 40
|
||||
];
|
||||
|
||||
/**
|
||||
* Type information coordinates.
|
||||
*/
|
||||
private const TYPE_INFO_COORDINATES = [
|
||||
[8, 0],
|
||||
[8, 1],
|
||||
[8, 2],
|
||||
[8, 3],
|
||||
[8, 4],
|
||||
[8, 5],
|
||||
[8, 7],
|
||||
[8, 8],
|
||||
[7, 8],
|
||||
[5, 8],
|
||||
[4, 8],
|
||||
[3, 8],
|
||||
[2, 8],
|
||||
[1, 8],
|
||||
[0, 8],
|
||||
];
|
||||
|
||||
/**
|
||||
* Version information polynomial.
|
||||
*/
|
||||
private const VERSION_INFO_POLY = 0x1f25;
|
||||
|
||||
/**
|
||||
* Type information polynomial.
|
||||
*/
|
||||
private const TYPE_INFO_POLY = 0x537;
|
||||
|
||||
/**
|
||||
* Type information mask pattern.
|
||||
*/
|
||||
private const TYPE_INFO_MASK_PATTERN = 0x5412;
|
||||
|
||||
/**
|
||||
* Clears a given matrix.
|
||||
*/
|
||||
public static function clearMatrix(ByteMatrix $matrix) : void
|
||||
{
|
||||
$matrix->clear(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a complete matrix.
|
||||
*/
|
||||
public static function buildMatrix(
|
||||
BitArray $dataBits,
|
||||
ErrorCorrectionLevel $level,
|
||||
Version $version,
|
||||
int $maskPattern,
|
||||
ByteMatrix $matrix
|
||||
) : void {
|
||||
self::clearMatrix($matrix);
|
||||
self::embedBasicPatterns($version, $matrix);
|
||||
self::embedTypeInfo($level, $maskPattern, $matrix);
|
||||
self::maybeEmbedVersionInfo($version, $matrix);
|
||||
self::embedDataBits($dataBits, $maskPattern, $matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the position detection patterns from a matrix.
|
||||
*
|
||||
* This can be useful if you need to render those patterns separately.
|
||||
*/
|
||||
public static function removePositionDetectionPatterns(ByteMatrix $matrix) : void
|
||||
{
|
||||
$pdpWidth = count(self::POSITION_DETECTION_PATTERN[0]);
|
||||
|
||||
self::removePositionDetectionPattern(0, 0, $matrix);
|
||||
self::removePositionDetectionPattern($matrix->getWidth() - $pdpWidth, 0, $matrix);
|
||||
self::removePositionDetectionPattern(0, $matrix->getWidth() - $pdpWidth, $matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds type information into a matrix.
|
||||
*/
|
||||
private static function embedTypeInfo(ErrorCorrectionLevel $level, int $maskPattern, ByteMatrix $matrix) : void
|
||||
{
|
||||
$typeInfoBits = new BitArray();
|
||||
self::makeTypeInfoBits($level, $maskPattern, $typeInfoBits);
|
||||
|
||||
$typeInfoBitsSize = $typeInfoBits->getSize();
|
||||
|
||||
for ($i = 0; $i < $typeInfoBitsSize; ++$i) {
|
||||
$bit = $typeInfoBits->get($typeInfoBitsSize - 1 - $i);
|
||||
|
||||
$x1 = self::TYPE_INFO_COORDINATES[$i][0];
|
||||
$y1 = self::TYPE_INFO_COORDINATES[$i][1];
|
||||
|
||||
$matrix->set($x1, $y1, (int) $bit);
|
||||
|
||||
if ($i < 8) {
|
||||
$x2 = $matrix->getWidth() - $i - 1;
|
||||
$y2 = 8;
|
||||
} else {
|
||||
$x2 = 8;
|
||||
$y2 = $matrix->getHeight() - 7 + ($i - 8);
|
||||
}
|
||||
|
||||
$matrix->set($x2, $y2, (int) $bit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates type information bits and appends them to a bit array.
|
||||
*
|
||||
* @throws RuntimeException if bit array resulted in invalid size
|
||||
*/
|
||||
private static function makeTypeInfoBits(ErrorCorrectionLevel $level, int $maskPattern, BitArray $bits) : void
|
||||
{
|
||||
$typeInfo = ($level->getBits() << 3) | $maskPattern;
|
||||
$bits->appendBits($typeInfo, 5);
|
||||
|
||||
$bchCode = self::calculateBchCode($typeInfo, self::TYPE_INFO_POLY);
|
||||
$bits->appendBits($bchCode, 10);
|
||||
|
||||
$maskBits = new BitArray();
|
||||
$maskBits->appendBits(self::TYPE_INFO_MASK_PATTERN, 15);
|
||||
$bits->xorBits($maskBits);
|
||||
|
||||
if (15 !== $bits->getSize()) {
|
||||
throw new RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds version information if required.
|
||||
*/
|
||||
private static function maybeEmbedVersionInfo(Version $version, ByteMatrix $matrix) : void
|
||||
{
|
||||
if ($version->getVersionNumber() < 7) {
|
||||
return;
|
||||
}
|
||||
|
||||
$versionInfoBits = new BitArray();
|
||||
self::makeVersionInfoBits($version, $versionInfoBits);
|
||||
|
||||
$bitIndex = 6 * 3 - 1;
|
||||
|
||||
for ($i = 0; $i < 6; ++$i) {
|
||||
for ($j = 0; $j < 3; ++$j) {
|
||||
$bit = $versionInfoBits->get($bitIndex);
|
||||
--$bitIndex;
|
||||
|
||||
$matrix->set($i, $matrix->getHeight() - 11 + $j, (int) $bit);
|
||||
$matrix->set($matrix->getHeight() - 11 + $j, $i, (int) $bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates version information bits and appends them to a bit array.
|
||||
*
|
||||
* @throws RuntimeException if bit array resulted in invalid size
|
||||
*/
|
||||
private static function makeVersionInfoBits(Version $version, BitArray $bits) : void
|
||||
{
|
||||
$bits->appendBits($version->getVersionNumber(), 6);
|
||||
|
||||
$bchCode = self::calculateBchCode($version->getVersionNumber(), self::VERSION_INFO_POLY);
|
||||
$bits->appendBits($bchCode, 12);
|
||||
|
||||
if (18 !== $bits->getSize()) {
|
||||
throw new RuntimeException('Bit array resulted in invalid size: ' . $bits->getSize());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the BCH code for a value and a polynomial.
|
||||
*/
|
||||
private static function calculateBchCode(int $value, int $poly) : int
|
||||
{
|
||||
$msbSetInPoly = self::findMsbSet($poly);
|
||||
$value <<= $msbSetInPoly - 1;
|
||||
|
||||
while (self::findMsbSet($value) >= $msbSetInPoly) {
|
||||
$value ^= $poly << (self::findMsbSet($value) - $msbSetInPoly);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and MSB set.
|
||||
*/
|
||||
private static function findMsbSet(int $value) : int
|
||||
{
|
||||
$numDigits = 0;
|
||||
|
||||
while (0 !== $value) {
|
||||
$value >>= 1;
|
||||
++$numDigits;
|
||||
}
|
||||
|
||||
return $numDigits;
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds basic patterns into a matrix.
|
||||
*/
|
||||
private static function embedBasicPatterns(Version $version, ByteMatrix $matrix) : void
|
||||
{
|
||||
self::embedPositionDetectionPatternsAndSeparators($matrix);
|
||||
self::embedDarkDotAtLeftBottomCorner($matrix);
|
||||
self::maybeEmbedPositionAdjustmentPatterns($version, $matrix);
|
||||
self::embedTimingPatterns($matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds position detection patterns and separators into a byte matrix.
|
||||
*/
|
||||
private static function embedPositionDetectionPatternsAndSeparators(ByteMatrix $matrix) : void
|
||||
{
|
||||
$pdpWidth = count(self::POSITION_DETECTION_PATTERN[0]);
|
||||
|
||||
self::embedPositionDetectionPattern(0, 0, $matrix);
|
||||
self::embedPositionDetectionPattern($matrix->getWidth() - $pdpWidth, 0, $matrix);
|
||||
self::embedPositionDetectionPattern(0, $matrix->getWidth() - $pdpWidth, $matrix);
|
||||
|
||||
$hspWidth = 8;
|
||||
|
||||
self::embedHorizontalSeparationPattern(0, $hspWidth - 1, $matrix);
|
||||
self::embedHorizontalSeparationPattern($matrix->getWidth() - $hspWidth, $hspWidth - 1, $matrix);
|
||||
self::embedHorizontalSeparationPattern(0, $matrix->getWidth() - $hspWidth, $matrix);
|
||||
|
||||
$vspSize = 7;
|
||||
|
||||
self::embedVerticalSeparationPattern($vspSize, 0, $matrix);
|
||||
self::embedVerticalSeparationPattern($matrix->getHeight() - $vspSize - 1, 0, $matrix);
|
||||
self::embedVerticalSeparationPattern($vspSize, $matrix->getHeight() - $vspSize, $matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds a single position detection pattern into a byte matrix.
|
||||
*/
|
||||
private static function embedPositionDetectionPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void
|
||||
{
|
||||
for ($y = 0; $y < 7; ++$y) {
|
||||
for ($x = 0; $x < 7; ++$x) {
|
||||
$matrix->set($xStart + $x, $yStart + $y, self::POSITION_DETECTION_PATTERN[$y][$x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static function removePositionDetectionPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void
|
||||
{
|
||||
for ($y = 0; $y < 7; ++$y) {
|
||||
for ($x = 0; $x < 7; ++$x) {
|
||||
$matrix->set($xStart + $x, $yStart + $y, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds a single horizontal separation pattern.
|
||||
*
|
||||
* @throws RuntimeException if a byte was already set
|
||||
*/
|
||||
private static function embedHorizontalSeparationPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void
|
||||
{
|
||||
for ($x = 0; $x < 8; $x++) {
|
||||
if (-1 !== $matrix->get($xStart + $x, $yStart)) {
|
||||
throw new RuntimeException('Byte already set');
|
||||
}
|
||||
|
||||
$matrix->set($xStart + $x, $yStart, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds a single vertical separation pattern.
|
||||
*
|
||||
* @throws RuntimeException if a byte was already set
|
||||
*/
|
||||
private static function embedVerticalSeparationPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void
|
||||
{
|
||||
for ($y = 0; $y < 7; $y++) {
|
||||
if (-1 !== $matrix->get($xStart, $yStart + $y)) {
|
||||
throw new RuntimeException('Byte already set');
|
||||
}
|
||||
|
||||
$matrix->set($xStart, $yStart + $y, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds a dot at the left bottom corner.
|
||||
*
|
||||
* @throws RuntimeException if a byte was already set to 0
|
||||
*/
|
||||
private static function embedDarkDotAtLeftBottomCorner(ByteMatrix $matrix) : void
|
||||
{
|
||||
if (0 === $matrix->get(8, $matrix->getHeight() - 8)) {
|
||||
throw new RuntimeException('Byte already set to 0');
|
||||
}
|
||||
|
||||
$matrix->set(8, $matrix->getHeight() - 8, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds position adjustment patterns if required.
|
||||
*/
|
||||
private static function maybeEmbedPositionAdjustmentPatterns(Version $version, ByteMatrix $matrix) : void
|
||||
{
|
||||
if ($version->getVersionNumber() < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
$index = $version->getVersionNumber() - 1;
|
||||
|
||||
$coordinates = self::POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[$index];
|
||||
$numCoordinates = count($coordinates);
|
||||
|
||||
for ($i = 0; $i < $numCoordinates; ++$i) {
|
||||
for ($j = 0; $j < $numCoordinates; ++$j) {
|
||||
$y = $coordinates[$i];
|
||||
$x = $coordinates[$j];
|
||||
|
||||
if (null === $x || null === $y) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (-1 === $matrix->get($x, $y)) {
|
||||
self::embedPositionAdjustmentPattern($x - 2, $y - 2, $matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds a single position adjustment pattern.
|
||||
*/
|
||||
private static function embedPositionAdjustmentPattern(int $xStart, int $yStart, ByteMatrix $matrix) : void
|
||||
{
|
||||
for ($y = 0; $y < 5; $y++) {
|
||||
for ($x = 0; $x < 5; $x++) {
|
||||
$matrix->set($xStart + $x, $yStart + $y, self::POSITION_ADJUSTMENT_PATTERN[$y][$x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds timing patterns into a matrix.
|
||||
*/
|
||||
private static function embedTimingPatterns(ByteMatrix $matrix) : void
|
||||
{
|
||||
$matrixWidth = $matrix->getWidth();
|
||||
|
||||
for ($i = 8; $i < $matrixWidth - 8; ++$i) {
|
||||
$bit = ($i + 1) % 2;
|
||||
|
||||
if (-1 === $matrix->get($i, 6)) {
|
||||
$matrix->set($i, 6, $bit);
|
||||
}
|
||||
|
||||
if (-1 === $matrix->get(6, $i)) {
|
||||
$matrix->set(6, $i, $bit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds "dataBits" using "getMaskPattern".
|
||||
*
|
||||
* For debugging purposes, it skips masking process if "getMaskPattern" is -1. See 8.7 of JISX0510:2004 (p.38) for
|
||||
* how to embed data bits.
|
||||
*
|
||||
* @throws WriterException if not all bits could be consumed
|
||||
*/
|
||||
private static function embedDataBits(BitArray $dataBits, int $maskPattern, ByteMatrix $matrix) : void
|
||||
{
|
||||
$bitIndex = 0;
|
||||
$direction = -1;
|
||||
|
||||
// Start from the right bottom cell.
|
||||
$x = $matrix->getWidth() - 1;
|
||||
$y = $matrix->getHeight() - 1;
|
||||
|
||||
while ($x > 0) {
|
||||
// Skip vertical timing pattern.
|
||||
if (6 === $x) {
|
||||
--$x;
|
||||
}
|
||||
|
||||
while ($y >= 0 && $y < $matrix->getHeight()) {
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$xx = $x - $i;
|
||||
|
||||
// Skip the cell if it's not empty.
|
||||
if (-1 !== $matrix->get($xx, $y)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($bitIndex < $dataBits->getSize()) {
|
||||
$bit = $dataBits->get($bitIndex);
|
||||
++$bitIndex;
|
||||
} else {
|
||||
// Padding bit. If there is no bit left, we'll fill the
|
||||
// left cells with 0, as described in 8.4.9 of
|
||||
// JISX0510:2004 (p. 24).
|
||||
$bit = false;
|
||||
}
|
||||
|
||||
// Skip masking if maskPattern is -1.
|
||||
if (-1 !== $maskPattern && MaskUtil::getDataMaskBit($maskPattern, $xx, $y)) {
|
||||
$bit = ! $bit;
|
||||
}
|
||||
|
||||
$matrix->set($xx, $y, (int) $bit);
|
||||
}
|
||||
|
||||
$y += $direction;
|
||||
}
|
||||
|
||||
$direction = -$direction;
|
||||
$y += $direction;
|
||||
$x -= 2;
|
||||
}
|
||||
|
||||
// All bits should be consumed
|
||||
if ($dataBits->getSize() !== $bitIndex) {
|
||||
throw new WriterException('Not all bits consumed (' . $bitIndex . ' out of ' . $dataBits->getSize() .')');
|
||||
}
|
||||
}
|
||||
}
|
141
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/QrCode.php
vendored
Normal file
141
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Encoder/QrCode.php
vendored
Normal file
|
@ -0,0 +1,141 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Encoder;
|
||||
|
||||
use BaconQrCode\Common\ErrorCorrectionLevel;
|
||||
use BaconQrCode\Common\Mode;
|
||||
use BaconQrCode\Common\Version;
|
||||
|
||||
/**
|
||||
* QR code.
|
||||
*/
|
||||
final class QrCode
|
||||
{
|
||||
/**
|
||||
* Number of possible mask patterns.
|
||||
*/
|
||||
public const NUM_MASK_PATTERNS = 8;
|
||||
|
||||
/**
|
||||
* Mode of the QR code.
|
||||
*
|
||||
* @var Mode
|
||||
*/
|
||||
private $mode;
|
||||
|
||||
/**
|
||||
* EC level of the QR code.
|
||||
*
|
||||
* @var ErrorCorrectionLevel
|
||||
*/
|
||||
private $errorCorrectionLevel;
|
||||
|
||||
/**
|
||||
* Version of the QR code.
|
||||
*
|
||||
* @var Version
|
||||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* Mask pattern of the QR code.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $maskPattern = -1;
|
||||
|
||||
/**
|
||||
* Matrix of the QR code.
|
||||
*
|
||||
* @var ByteMatrix
|
||||
*/
|
||||
private $matrix;
|
||||
|
||||
public function __construct(
|
||||
Mode $mode,
|
||||
ErrorCorrectionLevel $errorCorrectionLevel,
|
||||
Version $version,
|
||||
int $maskPattern,
|
||||
ByteMatrix $matrix
|
||||
) {
|
||||
$this->mode = $mode;
|
||||
$this->errorCorrectionLevel = $errorCorrectionLevel;
|
||||
$this->version = $version;
|
||||
$this->maskPattern = $maskPattern;
|
||||
$this->matrix = $matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mode.
|
||||
*/
|
||||
public function getMode() : Mode
|
||||
{
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EC level.
|
||||
*/
|
||||
public function getErrorCorrectionLevel() : ErrorCorrectionLevel
|
||||
{
|
||||
return $this->errorCorrectionLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the version.
|
||||
*/
|
||||
public function getVersion() : Version
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the mask pattern.
|
||||
*/
|
||||
public function getMaskPattern() : int
|
||||
{
|
||||
return $this->maskPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the matrix.
|
||||
*
|
||||
* @return ByteMatrix
|
||||
*/
|
||||
public function getMatrix()
|
||||
{
|
||||
return $this->matrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates whether a mask pattern is valid.
|
||||
*/
|
||||
public static function isValidMaskPattern(int $maskPattern) : bool
|
||||
{
|
||||
return $maskPattern > 0 && $maskPattern < self::NUM_MASK_PATTERNS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the QR code.
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
$result = "<<\n"
|
||||
. ' mode: ' . $this->mode . "\n"
|
||||
. ' ecLevel: ' . $this->errorCorrectionLevel . "\n"
|
||||
. ' version: ' . $this->version . "\n"
|
||||
. ' maskPattern: ' . $this->maskPattern . "\n";
|
||||
|
||||
if ($this->matrix === null) {
|
||||
$result .= " matrix: null\n";
|
||||
} else {
|
||||
$result .= " matrix:\n";
|
||||
$result .= $this->matrix;
|
||||
}
|
||||
|
||||
$result .= ">>\n";
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
10
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php
vendored
Normal file
10
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/ExceptionInterface.php
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Exception;
|
||||
|
||||
use Throwable;
|
||||
|
||||
interface ExceptionInterface extends Throwable
|
||||
{
|
||||
}
|
8
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/InvalidArgumentException.php
vendored
Normal file
8
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/InvalidArgumentException.php
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Exception;
|
||||
|
||||
final class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
8
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/OutOfBoundsException.php
vendored
Normal file
8
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/OutOfBoundsException.php
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Exception;
|
||||
|
||||
final class OutOfBoundsException extends \OutOfBoundsException implements ExceptionInterface
|
||||
{
|
||||
}
|
8
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/RuntimeException.php
vendored
Normal file
8
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/RuntimeException.php
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Exception;
|
||||
|
||||
final class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
8
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/UnexpectedValueException.php
vendored
Normal file
8
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/UnexpectedValueException.php
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Exception;
|
||||
|
||||
final class UnexpectedValueException extends \UnexpectedValueException implements ExceptionInterface
|
||||
{
|
||||
}
|
8
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/WriterException.php
vendored
Normal file
8
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Exception/WriterException.php
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Exception;
|
||||
|
||||
final class WriterException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
57
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Color/Alpha.php
vendored
Normal file
57
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Color/Alpha.php
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Color;
|
||||
|
||||
use BaconQrCode\Exception;
|
||||
|
||||
final class Alpha implements ColorInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $alpha;
|
||||
|
||||
/**
|
||||
* @var ColorInterface
|
||||
*/
|
||||
private $baseColor;
|
||||
|
||||
/**
|
||||
* @param int $alpha the alpha value, 0 to 100
|
||||
*/
|
||||
public function __construct(int $alpha, ColorInterface $baseColor)
|
||||
{
|
||||
if ($alpha < 0 || $alpha > 100) {
|
||||
throw new Exception\InvalidArgumentException('Alpha must be between 0 and 100');
|
||||
}
|
||||
|
||||
$this->alpha = $alpha;
|
||||
$this->baseColor = $baseColor;
|
||||
}
|
||||
|
||||
public function getAlpha() : int
|
||||
{
|
||||
return $this->alpha;
|
||||
}
|
||||
|
||||
public function getBaseColor() : ColorInterface
|
||||
{
|
||||
return $this->baseColor;
|
||||
}
|
||||
|
||||
public function toRgb() : Rgb
|
||||
{
|
||||
return $this->baseColor->toRgb();
|
||||
}
|
||||
|
||||
public function toCmyk() : Cmyk
|
||||
{
|
||||
return $this->baseColor->toCmyk();
|
||||
}
|
||||
|
||||
public function toGray() : Gray
|
||||
{
|
||||
return $this->baseColor->toGray();
|
||||
}
|
||||
}
|
103
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php
vendored
Normal file
103
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Color/Cmyk.php
vendored
Normal file
|
@ -0,0 +1,103 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Color;
|
||||
|
||||
use BaconQrCode\Exception;
|
||||
|
||||
final class Cmyk implements ColorInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $cyan;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $magenta;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $yellow;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $black;
|
||||
|
||||
/**
|
||||
* @param int $cyan the cyan amount, 0 to 100
|
||||
* @param int $magenta the magenta amount, 0 to 100
|
||||
* @param int $yellow the yellow amount, 0 to 100
|
||||
* @param int $black the black amount, 0 to 100
|
||||
*/
|
||||
public function __construct(int $cyan, int $magenta, int $yellow, int $black)
|
||||
{
|
||||
if ($cyan < 0 || $cyan > 100) {
|
||||
throw new Exception\InvalidArgumentException('Cyan must be between 0 and 100');
|
||||
}
|
||||
|
||||
if ($magenta < 0 || $magenta > 100) {
|
||||
throw new Exception\InvalidArgumentException('Magenta must be between 0 and 100');
|
||||
}
|
||||
|
||||
if ($yellow < 0 || $yellow > 100) {
|
||||
throw new Exception\InvalidArgumentException('Yellow must be between 0 and 100');
|
||||
}
|
||||
|
||||
if ($black < 0 || $black > 100) {
|
||||
throw new Exception\InvalidArgumentException('Black must be between 0 and 100');
|
||||
}
|
||||
|
||||
$this->cyan = $cyan;
|
||||
$this->magenta = $magenta;
|
||||
$this->yellow = $yellow;
|
||||
$this->black = $black;
|
||||
}
|
||||
|
||||
public function getCyan() : int
|
||||
{
|
||||
return $this->cyan;
|
||||
}
|
||||
|
||||
public function getMagenta() : int
|
||||
{
|
||||
return $this->magenta;
|
||||
}
|
||||
|
||||
public function getYellow() : int
|
||||
{
|
||||
return $this->yellow;
|
||||
}
|
||||
|
||||
public function getBlack() : int
|
||||
{
|
||||
return $this->black;
|
||||
}
|
||||
|
||||
public function toRgb() : Rgb
|
||||
{
|
||||
$k = $this->black / 100;
|
||||
$c = (-$k * $this->cyan + $k * 100 + $this->cyan) / 100;
|
||||
$m = (-$k * $this->magenta + $k * 100 + $this->magenta) / 100;
|
||||
$y = (-$k * $this->yellow + $k * 100 + $this->yellow) / 100;
|
||||
|
||||
return new Rgb(
|
||||
(int) (-$c * 255 + 255),
|
||||
(int) (-$m * 255 + 255),
|
||||
(int) (-$y * 255 + 255)
|
||||
);
|
||||
}
|
||||
|
||||
public function toCmyk() : Cmyk
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toGray() : Gray
|
||||
{
|
||||
return $this->toRgb()->toGray();
|
||||
}
|
||||
}
|
22
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php
vendored
Normal file
22
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Color/ColorInterface.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Color;
|
||||
|
||||
interface ColorInterface
|
||||
{
|
||||
/**
|
||||
* Converts the color to RGB.
|
||||
*/
|
||||
public function toRgb() : Rgb;
|
||||
|
||||
/**
|
||||
* Converts the color to CMYK.
|
||||
*/
|
||||
public function toCmyk() : Cmyk;
|
||||
|
||||
/**
|
||||
* Converts the color to gray.
|
||||
*/
|
||||
public function toGray() : Gray;
|
||||
}
|
46
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Color/Gray.php
vendored
Normal file
46
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Color/Gray.php
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Color;
|
||||
|
||||
use BaconQrCode\Exception;
|
||||
|
||||
final class Gray implements ColorInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $gray;
|
||||
|
||||
/**
|
||||
* @param int $gray the gray value between 0 (black) and 100 (white)
|
||||
*/
|
||||
public function __construct(int $gray)
|
||||
{
|
||||
if ($gray < 0 || $gray > 100) {
|
||||
throw new Exception\InvalidArgumentException('Gray must be between 0 and 100');
|
||||
}
|
||||
|
||||
$this->gray = (int) $gray;
|
||||
}
|
||||
|
||||
public function getGray() : int
|
||||
{
|
||||
return $this->gray;
|
||||
}
|
||||
|
||||
public function toRgb() : Rgb
|
||||
{
|
||||
return new Rgb((int) ($this->gray * 2.55), (int) ($this->gray * 2.55), (int) ($this->gray * 2.55));
|
||||
}
|
||||
|
||||
public function toCmyk() : Cmyk
|
||||
{
|
||||
return new Cmyk(0, 0, 0, 100 - $this->gray);
|
||||
}
|
||||
|
||||
public function toGray() : Gray
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
88
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php
vendored
Normal file
88
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Color/Rgb.php
vendored
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Color;
|
||||
|
||||
use BaconQrCode\Exception;
|
||||
|
||||
final class Rgb implements ColorInterface
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $red;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $green;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $blue;
|
||||
|
||||
/**
|
||||
* @param int $red the red amount of the color, 0 to 255
|
||||
* @param int $green the green amount of the color, 0 to 255
|
||||
* @param int $blue the blue amount of the color, 0 to 255
|
||||
*/
|
||||
public function __construct(int $red, int $green, int $blue)
|
||||
{
|
||||
if ($red < 0 || $red > 255) {
|
||||
throw new Exception\InvalidArgumentException('Red must be between 0 and 255');
|
||||
}
|
||||
|
||||
if ($green < 0 || $green > 255) {
|
||||
throw new Exception\InvalidArgumentException('Green must be between 0 and 255');
|
||||
}
|
||||
|
||||
if ($blue < 0 || $blue > 255) {
|
||||
throw new Exception\InvalidArgumentException('Blue must be between 0 and 255');
|
||||
}
|
||||
|
||||
$this->red = $red;
|
||||
$this->green = $green;
|
||||
$this->blue = $blue;
|
||||
}
|
||||
|
||||
public function getRed() : int
|
||||
{
|
||||
return $this->red;
|
||||
}
|
||||
|
||||
public function getGreen() : int
|
||||
{
|
||||
return $this->green;
|
||||
}
|
||||
|
||||
public function getBlue() : int
|
||||
{
|
||||
return $this->blue;
|
||||
}
|
||||
|
||||
public function toRgb() : Rgb
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function toCmyk() : Cmyk
|
||||
{
|
||||
$c = 1 - ($this->red / 255);
|
||||
$m = 1 - ($this->green / 255);
|
||||
$y = 1 - ($this->blue / 255);
|
||||
$k = min($c, $m, $y);
|
||||
|
||||
return new Cmyk(
|
||||
(int) (100 * ($c - $k) / (1 - $k)),
|
||||
(int) (100 * ($m - $k) / (1 - $k)),
|
||||
(int) (100 * ($y - $k) / (1 - $k)),
|
||||
(int) (100 * $k)
|
||||
);
|
||||
}
|
||||
|
||||
public function toGray() : Gray
|
||||
{
|
||||
return new Gray((int) (($this->red * 0.21 + $this->green * 0.71 + $this->blue * 0.07) / 2.55));
|
||||
}
|
||||
}
|
38
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php
vendored
Normal file
38
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Eye/CompositeEye.php
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Eye;
|
||||
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
|
||||
/**
|
||||
* Combines the style of two different eyes.
|
||||
*/
|
||||
final class CompositeEye implements EyeInterface
|
||||
{
|
||||
/**
|
||||
* @var EyeInterface
|
||||
*/
|
||||
private $externalEye;
|
||||
|
||||
/**
|
||||
* @var EyeInterface
|
||||
*/
|
||||
private $internalEye;
|
||||
|
||||
public function __construct(EyeInterface $externalEye, EyeInterface $internalEye)
|
||||
{
|
||||
$this->externalEye = $externalEye;
|
||||
$this->internalEye = $internalEye;
|
||||
}
|
||||
|
||||
public function getExternalPath() : Path
|
||||
{
|
||||
return $this->externalEye->getExternalPath();
|
||||
}
|
||||
|
||||
public function getInternalPath() : Path
|
||||
{
|
||||
return $this->internalEye->getInternalPath();
|
||||
}
|
||||
}
|
26
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php
vendored
Normal file
26
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Eye/EyeInterface.php
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Eye;
|
||||
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
|
||||
/**
|
||||
* Interface for describing the look of an eye.
|
||||
*/
|
||||
interface EyeInterface
|
||||
{
|
||||
/**
|
||||
* Returns the path of the external eye element.
|
||||
*
|
||||
* The path origin point (0, 0) must be anchored at the middle of the path.
|
||||
*/
|
||||
public function getExternalPath() : Path;
|
||||
|
||||
/**
|
||||
* Returns the path of the internal eye element.
|
||||
*
|
||||
* The path origin point (0, 0) must be anchored at the middle of the path.
|
||||
*/
|
||||
public function getInternalPath() : Path;
|
||||
}
|
54
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Eye/ModuleEye.php
vendored
Normal file
54
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Eye/ModuleEye.php
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Eye;
|
||||
|
||||
use BaconQrCode\Encoder\ByteMatrix;
|
||||
use BaconQrCode\Renderer\Module\ModuleInterface;
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
|
||||
/**
|
||||
* Renders an eye based on a module renderer.
|
||||
*/
|
||||
final class ModuleEye implements EyeInterface
|
||||
{
|
||||
/**
|
||||
* @var ModuleInterface
|
||||
*/
|
||||
private $module;
|
||||
|
||||
public function __construct(ModuleInterface $module)
|
||||
{
|
||||
$this->module = $module;
|
||||
}
|
||||
|
||||
public function getExternalPath() : Path
|
||||
{
|
||||
$matrix = new ByteMatrix(7, 7);
|
||||
|
||||
for ($x = 0; $x < 7; ++$x) {
|
||||
$matrix->set($x, 0, 1);
|
||||
$matrix->set($x, 6, 1);
|
||||
}
|
||||
|
||||
for ($y = 1; $y < 6; ++$y) {
|
||||
$matrix->set(0, $y, 1);
|
||||
$matrix->set(6, $y, 1);
|
||||
}
|
||||
|
||||
return $this->module->createPath($matrix)->translate(-3.5, -3.5);
|
||||
}
|
||||
|
||||
public function getInternalPath() : Path
|
||||
{
|
||||
$matrix = new ByteMatrix(3, 3);
|
||||
|
||||
for ($x = 0; $x < 3; ++$x) {
|
||||
for ($y = 0; $y < 3; ++$y) {
|
||||
$matrix->set($x, $y, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->module->createPath($matrix)->translate(-1.5, -1.5);
|
||||
}
|
||||
}
|
54
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php
vendored
Normal file
54
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SimpleCircleEye.php
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Eye;
|
||||
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
|
||||
/**
|
||||
* Renders the inner eye as a circle.
|
||||
*/
|
||||
final class SimpleCircleEye implements EyeInterface
|
||||
{
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function instance() : self
|
||||
{
|
||||
return self::$instance ?: self::$instance = new self();
|
||||
}
|
||||
|
||||
public function getExternalPath() : Path
|
||||
{
|
||||
return (new Path())
|
||||
->move(-3.5, -3.5)
|
||||
->line(3.5, -3.5)
|
||||
->line(3.5, 3.5)
|
||||
->line(-3.5, 3.5)
|
||||
->close()
|
||||
->move(-2.5, -2.5)
|
||||
->line(-2.5, 2.5)
|
||||
->line(2.5, 2.5)
|
||||
->line(2.5, -2.5)
|
||||
->close()
|
||||
;
|
||||
}
|
||||
|
||||
public function getInternalPath() : Path
|
||||
{
|
||||
return (new Path())
|
||||
->move(1.5, 0)
|
||||
->ellipticArc(1.5, 1.5, 0., false, true, 0., 1.5)
|
||||
->ellipticArc(1.5, 1.5, 0., false, true, -1.5, 0.)
|
||||
->ellipticArc(1.5, 1.5, 0., false, true, 0., -1.5)
|
||||
->ellipticArc(1.5, 1.5, 0., false, true, 1.5, 0.)
|
||||
->close()
|
||||
;
|
||||
}
|
||||
}
|
53
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php
vendored
Normal file
53
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Eye/SquareEye.php
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Eye;
|
||||
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
|
||||
/**
|
||||
* Renders the eyes in their default square shape.
|
||||
*/
|
||||
final class SquareEye implements EyeInterface
|
||||
{
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function instance() : self
|
||||
{
|
||||
return self::$instance ?: self::$instance = new self();
|
||||
}
|
||||
|
||||
public function getExternalPath() : Path
|
||||
{
|
||||
return (new Path())
|
||||
->move(-3.5, -3.5)
|
||||
->line(3.5, -3.5)
|
||||
->line(3.5, 3.5)
|
||||
->line(-3.5, 3.5)
|
||||
->close()
|
||||
->move(-2.5, -2.5)
|
||||
->line(-2.5, 2.5)
|
||||
->line(2.5, 2.5)
|
||||
->line(2.5, -2.5)
|
||||
->close()
|
||||
;
|
||||
}
|
||||
|
||||
public function getInternalPath() : Path
|
||||
{
|
||||
return (new Path())
|
||||
->move(-1.5, -1.5)
|
||||
->line(1.5, -1.5)
|
||||
->line(1.5, 1.5)
|
||||
->line(-1.5, 1.5)
|
||||
->close()
|
||||
;
|
||||
}
|
||||
}
|
376
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php
vendored
Normal file
376
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Image/EpsImageBackEnd.php
vendored
Normal file
|
@ -0,0 +1,376 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Image;
|
||||
|
||||
use BaconQrCode\Exception\RuntimeException;
|
||||
use BaconQrCode\Renderer\Color\Alpha;
|
||||
use BaconQrCode\Renderer\Color\Cmyk;
|
||||
use BaconQrCode\Renderer\Color\ColorInterface;
|
||||
use BaconQrCode\Renderer\Color\Gray;
|
||||
use BaconQrCode\Renderer\Color\Rgb;
|
||||
use BaconQrCode\Renderer\Path\Close;
|
||||
use BaconQrCode\Renderer\Path\Curve;
|
||||
use BaconQrCode\Renderer\Path\EllipticArc;
|
||||
use BaconQrCode\Renderer\Path\Line;
|
||||
use BaconQrCode\Renderer\Path\Move;
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
use BaconQrCode\Renderer\RendererStyle\Gradient;
|
||||
use BaconQrCode\Renderer\RendererStyle\GradientType;
|
||||
|
||||
final class EpsImageBackEnd implements ImageBackEndInterface
|
||||
{
|
||||
private const PRECISION = 3;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $eps;
|
||||
|
||||
public function new(int $size, ColorInterface $backgroundColor) : void
|
||||
{
|
||||
$this->eps = "%!PS-Adobe-3.0 EPSF-3.0\n"
|
||||
. "%%Creator: BaconQrCode\n"
|
||||
. sprintf("%%%%BoundingBox: 0 0 %d %d \n", $size, $size)
|
||||
. "%%BeginProlog\n"
|
||||
. "save\n"
|
||||
. "50 dict begin\n"
|
||||
. "/q { gsave } bind def\n"
|
||||
. "/Q { grestore } bind def\n"
|
||||
. "/s { scale } bind def\n"
|
||||
. "/t { translate } bind def\n"
|
||||
. "/r { rotate } bind def\n"
|
||||
. "/n { newpath } bind def\n"
|
||||
. "/m { moveto } bind def\n"
|
||||
. "/l { lineto } bind def\n"
|
||||
. "/c { curveto } bind def\n"
|
||||
. "/z { closepath } bind def\n"
|
||||
. "/f { eofill } bind def\n"
|
||||
. "/rgb { setrgbcolor } bind def\n"
|
||||
. "/cmyk { setcmykcolor } bind def\n"
|
||||
. "/gray { setgray } bind def\n"
|
||||
. "%%EndProlog\n"
|
||||
. "1 -1 s\n"
|
||||
. sprintf("0 -%d t\n", $size);
|
||||
|
||||
if ($backgroundColor instanceof Alpha && 0 === $backgroundColor->getAlpha()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->eps .= wordwrap(
|
||||
'0 0 m'
|
||||
. sprintf(' %s 0 l', (string) $size)
|
||||
. sprintf(' %s %s l', (string) $size, (string) $size)
|
||||
. sprintf(' 0 %s l', (string) $size)
|
||||
. ' z'
|
||||
. ' ' .$this->getColorSetString($backgroundColor) . " f\n",
|
||||
75,
|
||||
"\n "
|
||||
);
|
||||
}
|
||||
|
||||
public function scale(float $size) : void
|
||||
{
|
||||
if (null === $this->eps) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->eps .= sprintf("%1\$s %1\$s s\n", round($size, self::PRECISION));
|
||||
}
|
||||
|
||||
public function translate(float $x, float $y) : void
|
||||
{
|
||||
if (null === $this->eps) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->eps .= sprintf("%s %s t\n", round($x, self::PRECISION), round($y, self::PRECISION));
|
||||
}
|
||||
|
||||
public function rotate(int $degrees) : void
|
||||
{
|
||||
if (null === $this->eps) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->eps .= sprintf("%d r\n", $degrees);
|
||||
}
|
||||
|
||||
public function push() : void
|
||||
{
|
||||
if (null === $this->eps) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->eps .= "q\n";
|
||||
}
|
||||
|
||||
public function pop() : void
|
||||
{
|
||||
if (null === $this->eps) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->eps .= "Q\n";
|
||||
}
|
||||
|
||||
public function drawPathWithColor(Path $path, ColorInterface $color) : void
|
||||
{
|
||||
if (null === $this->eps) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$fromX = 0;
|
||||
$fromY = 0;
|
||||
$this->eps .= wordwrap(
|
||||
'n '
|
||||
. $this->drawPathOperations($path, $fromX, $fromY)
|
||||
. ' ' . $this->getColorSetString($color) . " f\n",
|
||||
75,
|
||||
"\n "
|
||||
);
|
||||
}
|
||||
|
||||
public function drawPathWithGradient(
|
||||
Path $path,
|
||||
Gradient $gradient,
|
||||
float $x,
|
||||
float $y,
|
||||
float $width,
|
||||
float $height
|
||||
) : void {
|
||||
if (null === $this->eps) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$fromX = 0;
|
||||
$fromY = 0;
|
||||
$this->eps .= wordwrap(
|
||||
'q n ' . $this->drawPathOperations($path, $fromX, $fromY) . "\n",
|
||||
75,
|
||||
"\n "
|
||||
);
|
||||
|
||||
$this->createGradientFill($gradient, $x, $y, $width, $height);
|
||||
}
|
||||
|
||||
public function done() : string
|
||||
{
|
||||
if (null === $this->eps) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->eps .= "%%TRAILER\nend restore\n%%EOF";
|
||||
$blob = $this->eps;
|
||||
$this->eps = null;
|
||||
|
||||
return $blob;
|
||||
}
|
||||
|
||||
private function drawPathOperations(Iterable $ops, &$fromX, &$fromY) : string
|
||||
{
|
||||
$pathData = [];
|
||||
|
||||
foreach ($ops as $op) {
|
||||
switch (true) {
|
||||
case $op instanceof Move:
|
||||
$fromX = $toX = round($op->getX(), self::PRECISION);
|
||||
$fromY = $toY = round($op->getY(), self::PRECISION);
|
||||
$pathData[] = sprintf('%s %s m', $toX, $toY);
|
||||
break;
|
||||
|
||||
case $op instanceof Line:
|
||||
$fromX = $toX = round($op->getX(), self::PRECISION);
|
||||
$fromY = $toY = round($op->getY(), self::PRECISION);
|
||||
$pathData[] = sprintf('%s %s l', $toX, $toY);
|
||||
break;
|
||||
|
||||
case $op instanceof EllipticArc:
|
||||
$pathData[] = $this->drawPathOperations($op->toCurves($fromX, $fromY), $fromX, $fromY);
|
||||
break;
|
||||
|
||||
case $op instanceof Curve:
|
||||
$x1 = round($op->getX1(), self::PRECISION);
|
||||
$y1 = round($op->getY1(), self::PRECISION);
|
||||
$x2 = round($op->getX2(), self::PRECISION);
|
||||
$y2 = round($op->getY2(), self::PRECISION);
|
||||
$fromX = $x3 = round($op->getX3(), self::PRECISION);
|
||||
$fromY = $y3 = round($op->getY3(), self::PRECISION);
|
||||
$pathData[] = sprintf('%s %s %s %s %s %s c', $x1, $y1, $x2, $y2, $x3, $y3);
|
||||
break;
|
||||
|
||||
case $op instanceof Close:
|
||||
$pathData[] = 'z';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException('Unexpected draw operation: ' . get_class($op));
|
||||
}
|
||||
}
|
||||
|
||||
return implode(' ', $pathData);
|
||||
}
|
||||
|
||||
private function createGradientFill(Gradient $gradient, float $x, float $y, float $width, float $height) : void
|
||||
{
|
||||
$startColor = $gradient->getStartColor();
|
||||
$endColor = $gradient->getEndColor();
|
||||
|
||||
if ($startColor instanceof Alpha) {
|
||||
$startColor = $startColor->getBaseColor();
|
||||
}
|
||||
|
||||
$startColorType = get_class($startColor);
|
||||
|
||||
if (! in_array($startColorType, [Rgb::class, Cmyk::class, Gray::class])) {
|
||||
$startColorType = Cmyk::class;
|
||||
$startColor = $startColor->toCmyk();
|
||||
}
|
||||
|
||||
if (get_class($endColor) !== $startColorType) {
|
||||
switch ($startColorType) {
|
||||
case Cmyk::class:
|
||||
$endColor = $endColor->toCmyk();
|
||||
break;
|
||||
|
||||
case Rgb::class:
|
||||
$endColor = $endColor->toRgb();
|
||||
break;
|
||||
|
||||
case Gray::class:
|
||||
$endColor = $endColor->toGray();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->eps .= "eoclip\n<<\n";
|
||||
|
||||
if ($gradient->getType() === GradientType::RADIAL()) {
|
||||
$this->eps .= " /ShadingType 3\n";
|
||||
} else {
|
||||
$this->eps .= " /ShadingType 2\n";
|
||||
}
|
||||
|
||||
$this->eps .= " /Extend [ true true ]\n"
|
||||
. " /AntiAlias true\n";
|
||||
|
||||
switch ($startColorType) {
|
||||
case Cmyk::class:
|
||||
$this->eps .= " /ColorSpace /DeviceCMYK\n";
|
||||
break;
|
||||
|
||||
case Rgb::class:
|
||||
$this->eps .= " /ColorSpace /DeviceRGB\n";
|
||||
break;
|
||||
|
||||
case Gray::class:
|
||||
$this->eps .= " /ColorSpace /DeviceGray\n";
|
||||
break;
|
||||
}
|
||||
|
||||
switch ($gradient->getType()) {
|
||||
case GradientType::HORIZONTAL():
|
||||
$this->eps .= sprintf(
|
||||
" /Coords [ %s %s %s %s ]\n",
|
||||
round($x, self::PRECISION),
|
||||
round($y, self::PRECISION),
|
||||
round($x + $width, self::PRECISION),
|
||||
round($y, self::PRECISION)
|
||||
);
|
||||
break;
|
||||
|
||||
case GradientType::VERTICAL():
|
||||
$this->eps .= sprintf(
|
||||
" /Coords [ %s %s %s %s ]\n",
|
||||
round($x, self::PRECISION),
|
||||
round($y, self::PRECISION),
|
||||
round($x, self::PRECISION),
|
||||
round($y + $height, self::PRECISION)
|
||||
);
|
||||
break;
|
||||
|
||||
case GradientType::DIAGONAL():
|
||||
$this->eps .= sprintf(
|
||||
" /Coords [ %s %s %s %s ]\n",
|
||||
round($x, self::PRECISION),
|
||||
round($y, self::PRECISION),
|
||||
round($x + $width, self::PRECISION),
|
||||
round($y + $height, self::PRECISION)
|
||||
);
|
||||
break;
|
||||
|
||||
case GradientType::INVERSE_DIAGONAL():
|
||||
$this->eps .= sprintf(
|
||||
" /Coords [ %s %s %s %s ]\n",
|
||||
round($x, self::PRECISION),
|
||||
round($y + $height, self::PRECISION),
|
||||
round($x + $width, self::PRECISION),
|
||||
round($y, self::PRECISION)
|
||||
);
|
||||
break;
|
||||
|
||||
case GradientType::RADIAL():
|
||||
$centerX = ($x + $width) / 2;
|
||||
$centerY = ($y + $height) / 2;
|
||||
|
||||
$this->eps .= sprintf(
|
||||
" /Coords [ %s %s 0 %s %s %s ]\n",
|
||||
round($centerX, self::PRECISION),
|
||||
round($centerY, self::PRECISION),
|
||||
round($centerX, self::PRECISION),
|
||||
round($centerY, self::PRECISION),
|
||||
round(max($width, $height) / 2, self::PRECISION)
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
$this->eps .= " /Function\n"
|
||||
. " <<\n"
|
||||
. " /FunctionType 2\n"
|
||||
. " /Domain [ 0 1 ]\n"
|
||||
. sprintf(" /C0 [ %s ]\n", $this->getColorString($startColor))
|
||||
. sprintf(" /C1 [ %s ]\n", $this->getColorString($endColor))
|
||||
. " /N 1\n"
|
||||
. " >>\n>>\nshfill\nQ\n";
|
||||
}
|
||||
|
||||
private function getColorSetString(ColorInterface $color) : string
|
||||
{
|
||||
if ($color instanceof Rgb) {
|
||||
return $this->getColorString($color) . ' rgb';
|
||||
}
|
||||
|
||||
if ($color instanceof Cmyk) {
|
||||
return $this->getColorString($color) . ' cmyk';
|
||||
}
|
||||
|
||||
if ($color instanceof Gray) {
|
||||
return $this->getColorString($color) . ' gray';
|
||||
}
|
||||
|
||||
return $this->getColorSetString($color->toCmyk());
|
||||
}
|
||||
|
||||
private function getColorString(ColorInterface $color) : string
|
||||
{
|
||||
if ($color instanceof Rgb) {
|
||||
return sprintf('%s %s %s', $color->getRed() / 255, $color->getGreen() / 255, $color->getBlue() / 255);
|
||||
}
|
||||
|
||||
if ($color instanceof Cmyk) {
|
||||
return sprintf(
|
||||
'%s %s %s %s',
|
||||
$color->getCyan() / 100,
|
||||
$color->getMagenta() / 100,
|
||||
$color->getYellow() / 100,
|
||||
$color->getBlack() / 100
|
||||
);
|
||||
}
|
||||
|
||||
if ($color instanceof Gray) {
|
||||
return sprintf('%s', $color->getGray() / 100);
|
||||
}
|
||||
|
||||
return $this->getColorString($color->toCmyk());
|
||||
}
|
||||
}
|
87
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php
vendored
Normal file
87
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImageBackEndInterface.php
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Image;
|
||||
|
||||
use BaconQrCode\Exception\RuntimeException;
|
||||
use BaconQrCode\Renderer\Color\ColorInterface;
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
use BaconQrCode\Renderer\RendererStyle\Gradient;
|
||||
|
||||
/**
|
||||
* Interface for back ends able to to produce path based images.
|
||||
*/
|
||||
interface ImageBackEndInterface
|
||||
{
|
||||
/**
|
||||
* Starts a new image.
|
||||
*
|
||||
* If a previous image was already started, previous data get erased.
|
||||
*/
|
||||
public function new(int $size, ColorInterface $backgroundColor) : void;
|
||||
|
||||
/**
|
||||
* Transforms all following drawing operation coordinates by scaling them by a given factor.
|
||||
*
|
||||
* @throws RuntimeException if no image was started yet.
|
||||
*/
|
||||
public function scale(float $size) : void;
|
||||
|
||||
/**
|
||||
* Transforms all following drawing operation coordinates by translating them by a given amount.
|
||||
*
|
||||
* @throws RuntimeException if no image was started yet.
|
||||
*/
|
||||
public function translate(float $x, float $y) : void;
|
||||
|
||||
/**
|
||||
* Transforms all following drawing operation coordinates by rotating them by a given amount.
|
||||
*
|
||||
* @throws RuntimeException if no image was started yet.
|
||||
*/
|
||||
public function rotate(int $degrees) : void;
|
||||
|
||||
/**
|
||||
* Pushes the current coordinate transformation onto a stack.
|
||||
*
|
||||
* @throws RuntimeException if no image was started yet.
|
||||
*/
|
||||
public function push() : void;
|
||||
|
||||
/**
|
||||
* Pops the last coordinate transformation from a stack.
|
||||
*
|
||||
* @throws RuntimeException if no image was started yet.
|
||||
*/
|
||||
public function pop() : void;
|
||||
|
||||
/**
|
||||
* Draws a path with a given color.
|
||||
*
|
||||
* @throws RuntimeException if no image was started yet.
|
||||
*/
|
||||
public function drawPathWithColor(Path $path, ColorInterface $color) : void;
|
||||
|
||||
/**
|
||||
* Draws a path with a given gradient which spans the box described by the position and size.
|
||||
*
|
||||
* @throws RuntimeException if no image was started yet.
|
||||
*/
|
||||
public function drawPathWithGradient(
|
||||
Path $path,
|
||||
Gradient $gradient,
|
||||
float $x,
|
||||
float $y,
|
||||
float $width,
|
||||
float $height
|
||||
) : void;
|
||||
|
||||
/**
|
||||
* Ends the image drawing operation and returns the resulting blob.
|
||||
*
|
||||
* This should reset the state of the back end and thus this method should only be callable once per image.
|
||||
*
|
||||
* @throws RuntimeException if no image was started yet.
|
||||
*/
|
||||
public function done() : string;
|
||||
}
|
336
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImagickImageBackEnd.php
vendored
Normal file
336
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Image/ImagickImageBackEnd.php
vendored
Normal file
|
@ -0,0 +1,336 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Image;
|
||||
|
||||
use BaconQrCode\Exception\RuntimeException;
|
||||
use BaconQrCode\Renderer\Color\Alpha;
|
||||
use BaconQrCode\Renderer\Color\Cmyk;
|
||||
use BaconQrCode\Renderer\Color\ColorInterface;
|
||||
use BaconQrCode\Renderer\Color\Gray;
|
||||
use BaconQrCode\Renderer\Color\Rgb;
|
||||
use BaconQrCode\Renderer\Path\Close;
|
||||
use BaconQrCode\Renderer\Path\Curve;
|
||||
use BaconQrCode\Renderer\Path\EllipticArc;
|
||||
use BaconQrCode\Renderer\Path\Line;
|
||||
use BaconQrCode\Renderer\Path\Move;
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
use BaconQrCode\Renderer\RendererStyle\Gradient;
|
||||
use BaconQrCode\Renderer\RendererStyle\GradientType;
|
||||
use Imagick;
|
||||
use ImagickDraw;
|
||||
use ImagickPixel;
|
||||
|
||||
final class ImagickImageBackEnd implements ImageBackEndInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $imageFormat;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $compressionQuality;
|
||||
|
||||
/**
|
||||
* @var Imagick|null
|
||||
*/
|
||||
private $image;
|
||||
|
||||
/**
|
||||
* @var ImagickDraw|null
|
||||
*/
|
||||
private $draw;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $gradientCount;
|
||||
|
||||
/**
|
||||
* @var TransformationMatrix[]|null
|
||||
*/
|
||||
private $matrices;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $matrixIndex;
|
||||
|
||||
public function __construct(string $imageFormat = 'png', int $compressionQuality = 100)
|
||||
{
|
||||
if (! class_exists(Imagick::class)) {
|
||||
throw new RuntimeException('You need to install the imagick extension to use this back end');
|
||||
}
|
||||
|
||||
$this->imageFormat = $imageFormat;
|
||||
$this->compressionQuality = $compressionQuality;
|
||||
}
|
||||
|
||||
public function new(int $size, ColorInterface $backgroundColor) : void
|
||||
{
|
||||
$this->image = new Imagick();
|
||||
$this->image->newImage($size, $size, $this->getColorPixel($backgroundColor));
|
||||
$this->image->setImageFormat($this->imageFormat);
|
||||
$this->image->setCompressionQuality($this->compressionQuality);
|
||||
$this->draw = new ImagickDraw();
|
||||
$this->gradientCount = 0;
|
||||
$this->matrices = [new TransformationMatrix()];
|
||||
$this->matrixIndex = 0;
|
||||
}
|
||||
|
||||
public function scale(float $size) : void
|
||||
{
|
||||
if (null === $this->draw) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->draw->scale($size, $size);
|
||||
$this->matrices[$this->matrixIndex] = $this->matrices[$this->matrixIndex]
|
||||
->multiply(TransformationMatrix::scale($size));
|
||||
}
|
||||
|
||||
public function translate(float $x, float $y) : void
|
||||
{
|
||||
if (null === $this->draw) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->draw->translate($x, $y);
|
||||
$this->matrices[$this->matrixIndex] = $this->matrices[$this->matrixIndex]
|
||||
->multiply(TransformationMatrix::translate($x, $y));
|
||||
}
|
||||
|
||||
public function rotate(int $degrees) : void
|
||||
{
|
||||
if (null === $this->draw) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->draw->rotate($degrees);
|
||||
$this->matrices[$this->matrixIndex] = $this->matrices[$this->matrixIndex]
|
||||
->multiply(TransformationMatrix::rotate($degrees));
|
||||
}
|
||||
|
||||
public function push() : void
|
||||
{
|
||||
if (null === $this->draw) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->draw->push();
|
||||
$this->matrices[++$this->matrixIndex] = $this->matrices[$this->matrixIndex - 1];
|
||||
}
|
||||
|
||||
public function pop() : void
|
||||
{
|
||||
if (null === $this->draw) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->draw->pop();
|
||||
unset($this->matrices[$this->matrixIndex--]);
|
||||
}
|
||||
|
||||
public function drawPathWithColor(Path $path, ColorInterface $color) : void
|
||||
{
|
||||
if (null === $this->draw) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->draw->setFillColor($this->getColorPixel($color));
|
||||
$this->drawPath($path);
|
||||
}
|
||||
|
||||
public function drawPathWithGradient(
|
||||
Path $path,
|
||||
Gradient $gradient,
|
||||
float $x,
|
||||
float $y,
|
||||
float $width,
|
||||
float $height
|
||||
) : void {
|
||||
if (null === $this->draw) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->draw->setFillPatternURL('#' . $this->createGradientFill($gradient, $x, $y, $width, $height));
|
||||
$this->drawPath($path);
|
||||
}
|
||||
|
||||
public function done() : string
|
||||
{
|
||||
if (null === $this->draw) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->image->drawImage($this->draw);
|
||||
$blob = $this->image->getImageBlob();
|
||||
$this->draw->clear();
|
||||
$this->image->clear();
|
||||
$this->draw = null;
|
||||
$this->image = null;
|
||||
$this->gradientCount = null;
|
||||
|
||||
return $blob;
|
||||
}
|
||||
|
||||
private function drawPath(Path $path) : void
|
||||
{
|
||||
$this->draw->pathStart();
|
||||
|
||||
foreach ($path as $op) {
|
||||
switch (true) {
|
||||
case $op instanceof Move:
|
||||
$this->draw->pathMoveToAbsolute($op->getX(), $op->getY());
|
||||
break;
|
||||
|
||||
case $op instanceof Line:
|
||||
$this->draw->pathLineToAbsolute($op->getX(), $op->getY());
|
||||
break;
|
||||
|
||||
case $op instanceof EllipticArc:
|
||||
$this->draw->pathEllipticArcAbsolute(
|
||||
$op->getXRadius(),
|
||||
$op->getYRadius(),
|
||||
$op->getXAxisAngle(),
|
||||
$op->isLargeArc(),
|
||||
$op->isSweep(),
|
||||
$op->getX(),
|
||||
$op->getY()
|
||||
);
|
||||
break;
|
||||
|
||||
case $op instanceof Curve:
|
||||
$this->draw->pathCurveToAbsolute(
|
||||
$op->getX1(),
|
||||
$op->getY1(),
|
||||
$op->getX2(),
|
||||
$op->getY2(),
|
||||
$op->getX3(),
|
||||
$op->getY3()
|
||||
);
|
||||
break;
|
||||
|
||||
case $op instanceof Close:
|
||||
$this->draw->pathClose();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException('Unexpected draw operation: ' . get_class($op));
|
||||
}
|
||||
}
|
||||
|
||||
$this->draw->pathFinish();
|
||||
}
|
||||
|
||||
private function createGradientFill(Gradient $gradient, float $x, float $y, float $width, float $height) : string
|
||||
{
|
||||
list($width, $height) = $this->matrices[$this->matrixIndex]->apply($width, $height);
|
||||
|
||||
$startColor = $this->getColorPixel($gradient->getStartColor())->getColorAsString();
|
||||
$endColor = $this->getColorPixel($gradient->getEndColor())->getColorAsString();
|
||||
$gradientImage = new Imagick();
|
||||
|
||||
switch ($gradient->getType()) {
|
||||
case GradientType::HORIZONTAL():
|
||||
$gradientImage->newPseudoImage((int) $height, (int) $width, sprintf(
|
||||
'gradient:%s-%s',
|
||||
$startColor,
|
||||
$endColor
|
||||
));
|
||||
$gradientImage->rotateImage('transparent', -90);
|
||||
break;
|
||||
|
||||
case GradientType::VERTICAL():
|
||||
$gradientImage->newPseudoImage((int) $width, (int) $height, sprintf(
|
||||
'gradient:%s-%s',
|
||||
$startColor,
|
||||
$endColor
|
||||
));
|
||||
break;
|
||||
|
||||
case GradientType::DIAGONAL():
|
||||
case GradientType::INVERSE_DIAGONAL():
|
||||
$gradientImage->newPseudoImage((int) ($width * sqrt(2)), (int) ($height * sqrt(2)), sprintf(
|
||||
'gradient:%s-%s',
|
||||
$startColor,
|
||||
$endColor
|
||||
));
|
||||
|
||||
if (GradientType::DIAGONAL() === $gradient->getType()) {
|
||||
$gradientImage->rotateImage('transparent', -45);
|
||||
} else {
|
||||
$gradientImage->rotateImage('transparent', -135);
|
||||
}
|
||||
|
||||
$rotatedWidth = $gradientImage->getImageWidth();
|
||||
$rotatedHeight = $gradientImage->getImageHeight();
|
||||
|
||||
$gradientImage->setImagePage($rotatedWidth, $rotatedHeight, 0, 0);
|
||||
$gradientImage->cropImage(
|
||||
intdiv($rotatedWidth, 2) - 2,
|
||||
intdiv($rotatedHeight, 2) - 2,
|
||||
intdiv($rotatedWidth, 4) + 1,
|
||||
intdiv($rotatedWidth, 4) + 1
|
||||
);
|
||||
break;
|
||||
|
||||
case GradientType::RADIAL():
|
||||
$gradientImage->newPseudoImage((int) $width, (int) $height, sprintf(
|
||||
'radial-gradient:%s-%s',
|
||||
$startColor,
|
||||
$endColor
|
||||
));
|
||||
break;
|
||||
}
|
||||
|
||||
$id = sprintf('g%d', ++$this->gradientCount);
|
||||
$this->draw->pushPattern($id, 0, 0, $width, $height);
|
||||
$this->draw->composite(Imagick::COMPOSITE_COPY, 0, 0, $width, $height, $gradientImage);
|
||||
$this->draw->popPattern();
|
||||
return $id;
|
||||
}
|
||||
|
||||
private function getColorPixel(ColorInterface $color) : ImagickPixel
|
||||
{
|
||||
$alpha = 100;
|
||||
|
||||
if ($color instanceof Alpha) {
|
||||
$alpha = $color->getAlpha();
|
||||
$color = $color->getBaseColor();
|
||||
}
|
||||
|
||||
if ($color instanceof Rgb) {
|
||||
return new ImagickPixel(sprintf(
|
||||
'rgba(%d, %d, %d, %F)',
|
||||
$color->getRed(),
|
||||
$color->getGreen(),
|
||||
$color->getBlue(),
|
||||
$alpha / 100
|
||||
));
|
||||
}
|
||||
|
||||
if ($color instanceof Cmyk) {
|
||||
return new ImagickPixel(sprintf(
|
||||
'cmyka(%d, %d, %d, %d, %F)',
|
||||
$color->getCyan(),
|
||||
$color->getMagenta(),
|
||||
$color->getYellow(),
|
||||
$color->getBlack(),
|
||||
$alpha / 100
|
||||
));
|
||||
}
|
||||
|
||||
if ($color instanceof Gray) {
|
||||
return new ImagickPixel(sprintf(
|
||||
'graya(%d%%, %F)',
|
||||
$color->getGray(),
|
||||
$alpha / 100
|
||||
));
|
||||
}
|
||||
|
||||
return $this->getColorPixel(new Alpha($alpha, $color->toRgb()));
|
||||
}
|
||||
}
|
369
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php
vendored
Normal file
369
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Image/SvgImageBackEnd.php
vendored
Normal file
|
@ -0,0 +1,369 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Image;
|
||||
|
||||
use BaconQrCode\Exception\RuntimeException;
|
||||
use BaconQrCode\Renderer\Color\Alpha;
|
||||
use BaconQrCode\Renderer\Color\ColorInterface;
|
||||
use BaconQrCode\Renderer\Path\Close;
|
||||
use BaconQrCode\Renderer\Path\Curve;
|
||||
use BaconQrCode\Renderer\Path\EllipticArc;
|
||||
use BaconQrCode\Renderer\Path\Line;
|
||||
use BaconQrCode\Renderer\Path\Move;
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
use BaconQrCode\Renderer\RendererStyle\Gradient;
|
||||
use BaconQrCode\Renderer\RendererStyle\GradientType;
|
||||
use XMLWriter;
|
||||
|
||||
final class SvgImageBackEnd implements ImageBackEndInterface
|
||||
{
|
||||
private const PRECISION = 3;
|
||||
|
||||
/**
|
||||
* @var XMLWriter|null
|
||||
*/
|
||||
private $xmlWriter;
|
||||
|
||||
/**
|
||||
* @var int[]|null
|
||||
*/
|
||||
private $stack;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $currentStack;
|
||||
|
||||
/**
|
||||
* @var int|null
|
||||
*/
|
||||
private $gradientCount;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if (! class_exists(XMLWriter::class)) {
|
||||
throw new RuntimeException('You need to install the libxml extension to use this back end');
|
||||
}
|
||||
}
|
||||
|
||||
public function new(int $size, ColorInterface $backgroundColor) : void
|
||||
{
|
||||
$this->xmlWriter = new XMLWriter();
|
||||
$this->xmlWriter->openMemory();
|
||||
|
||||
$this->xmlWriter->startDocument('1.0', 'UTF-8');
|
||||
$this->xmlWriter->startElement('svg');
|
||||
$this->xmlWriter->writeAttribute('xmlns', 'http://www.w3.org/2000/svg');
|
||||
$this->xmlWriter->writeAttribute('version', '1.1');
|
||||
$this->xmlWriter->writeAttribute('width', (string) $size);
|
||||
$this->xmlWriter->writeAttribute('height', (string) $size);
|
||||
$this->xmlWriter->writeAttribute('viewBox', '0 0 '. $size . ' ' . $size);
|
||||
|
||||
$this->gradientCount = 0;
|
||||
$this->currentStack = 0;
|
||||
$this->stack[0] = 0;
|
||||
|
||||
$alpha = 1;
|
||||
|
||||
if ($backgroundColor instanceof Alpha) {
|
||||
$alpha = $backgroundColor->getAlpha() / 100;
|
||||
}
|
||||
|
||||
if (0 === $alpha) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->xmlWriter->startElement('rect');
|
||||
$this->xmlWriter->writeAttribute('x', '0');
|
||||
$this->xmlWriter->writeAttribute('y', '0');
|
||||
$this->xmlWriter->writeAttribute('width', (string) $size);
|
||||
$this->xmlWriter->writeAttribute('height', (string) $size);
|
||||
$this->xmlWriter->writeAttribute('fill', $this->getColorString($backgroundColor));
|
||||
|
||||
if ($alpha < 1) {
|
||||
$this->xmlWriter->writeAttribute('fill-opacity', (string) $alpha);
|
||||
}
|
||||
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
|
||||
public function scale(float $size) : void
|
||||
{
|
||||
if (null === $this->xmlWriter) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->xmlWriter->startElement('g');
|
||||
$this->xmlWriter->writeAttribute(
|
||||
'transform',
|
||||
sprintf('scale(%s)', round($size, self::PRECISION))
|
||||
);
|
||||
++$this->stack[$this->currentStack];
|
||||
}
|
||||
|
||||
public function translate(float $x, float $y) : void
|
||||
{
|
||||
if (null === $this->xmlWriter) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->xmlWriter->startElement('g');
|
||||
$this->xmlWriter->writeAttribute(
|
||||
'transform',
|
||||
sprintf('translate(%s,%s)', round($x, self::PRECISION), round($y, self::PRECISION))
|
||||
);
|
||||
++$this->stack[$this->currentStack];
|
||||
}
|
||||
|
||||
public function rotate(int $degrees) : void
|
||||
{
|
||||
if (null === $this->xmlWriter) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->xmlWriter->startElement('g');
|
||||
$this->xmlWriter->writeAttribute('transform', sprintf('rotate(%d)', $degrees));
|
||||
++$this->stack[$this->currentStack];
|
||||
}
|
||||
|
||||
public function push() : void
|
||||
{
|
||||
if (null === $this->xmlWriter) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$this->xmlWriter->startElement('g');
|
||||
$this->stack[] = 1;
|
||||
++$this->currentStack;
|
||||
}
|
||||
|
||||
public function pop() : void
|
||||
{
|
||||
if (null === $this->xmlWriter) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
for ($i = 0; $i < $this->stack[$this->currentStack]; ++$i) {
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
|
||||
array_pop($this->stack);
|
||||
--$this->currentStack;
|
||||
}
|
||||
|
||||
public function drawPathWithColor(Path $path, ColorInterface $color) : void
|
||||
{
|
||||
if (null === $this->xmlWriter) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$alpha = 1;
|
||||
|
||||
if ($color instanceof Alpha) {
|
||||
$alpha = $color->getAlpha() / 100;
|
||||
}
|
||||
|
||||
$this->startPathElement($path);
|
||||
$this->xmlWriter->writeAttribute('fill', $this->getColorString($color));
|
||||
|
||||
if ($alpha < 1) {
|
||||
$this->xmlWriter->writeAttribute('fill-opacity', (string) $alpha);
|
||||
}
|
||||
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
|
||||
public function drawPathWithGradient(
|
||||
Path $path,
|
||||
Gradient $gradient,
|
||||
float $x,
|
||||
float $y,
|
||||
float $width,
|
||||
float $height
|
||||
) : void {
|
||||
if (null === $this->xmlWriter) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
$gradientId = $this->createGradientFill($gradient, $x, $y, $width, $height);
|
||||
$this->startPathElement($path);
|
||||
$this->xmlWriter->writeAttribute('fill', 'url(#' . $gradientId . ')');
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
|
||||
public function done() : string
|
||||
{
|
||||
if (null === $this->xmlWriter) {
|
||||
throw new RuntimeException('No image has been started');
|
||||
}
|
||||
|
||||
foreach ($this->stack as $openElements) {
|
||||
for ($i = $openElements; $i > 0; --$i) {
|
||||
$this->xmlWriter->endElement();
|
||||
}
|
||||
}
|
||||
|
||||
$this->xmlWriter->endDocument();
|
||||
$blob = $this->xmlWriter->outputMemory(true);
|
||||
$this->xmlWriter = null;
|
||||
$this->stack = null;
|
||||
$this->currentStack = null;
|
||||
$this->gradientCount = null;
|
||||
|
||||
return $blob;
|
||||
}
|
||||
|
||||
private function startPathElement(Path $path) : void
|
||||
{
|
||||
$pathData = [];
|
||||
|
||||
foreach ($path as $op) {
|
||||
switch (true) {
|
||||
case $op instanceof Move:
|
||||
$pathData[] = sprintf(
|
||||
'M%s %s',
|
||||
round($op->getX(), self::PRECISION),
|
||||
round($op->getY(), self::PRECISION)
|
||||
);
|
||||
break;
|
||||
|
||||
case $op instanceof Line:
|
||||
$pathData[] = sprintf(
|
||||
'L%s %s',
|
||||
round($op->getX(), self::PRECISION),
|
||||
round($op->getY(), self::PRECISION)
|
||||
);
|
||||
break;
|
||||
|
||||
case $op instanceof EllipticArc:
|
||||
$pathData[] = sprintf(
|
||||
'A%s %s %s %u %u %s %s',
|
||||
round($op->getXRadius(), self::PRECISION),
|
||||
round($op->getYRadius(), self::PRECISION),
|
||||
round($op->getXAxisAngle(), self::PRECISION),
|
||||
$op->isLargeArc(),
|
||||
$op->isSweep(),
|
||||
round($op->getX(), self::PRECISION),
|
||||
round($op->getY(), self::PRECISION)
|
||||
);
|
||||
break;
|
||||
|
||||
case $op instanceof Curve:
|
||||
$pathData[] = sprintf(
|
||||
'C%s %s %s %s %s %s',
|
||||
round($op->getX1(), self::PRECISION),
|
||||
round($op->getY1(), self::PRECISION),
|
||||
round($op->getX2(), self::PRECISION),
|
||||
round($op->getY2(), self::PRECISION),
|
||||
round($op->getX3(), self::PRECISION),
|
||||
round($op->getY3(), self::PRECISION)
|
||||
);
|
||||
break;
|
||||
|
||||
case $op instanceof Close:
|
||||
$pathData[] = 'Z';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new RuntimeException('Unexpected draw operation: ' . get_class($op));
|
||||
}
|
||||
}
|
||||
|
||||
$this->xmlWriter->startElement('path');
|
||||
$this->xmlWriter->writeAttribute('fill-rule', 'evenodd');
|
||||
$this->xmlWriter->writeAttribute('d', implode('', $pathData));
|
||||
}
|
||||
|
||||
private function createGradientFill(Gradient $gradient, float $x, float $y, float $width, float $height) : string
|
||||
{
|
||||
$this->xmlWriter->startElement('defs');
|
||||
|
||||
$startColor = $gradient->getStartColor();
|
||||
$endColor = $gradient->getEndColor();
|
||||
|
||||
if ($gradient->getType() === GradientType::RADIAL()) {
|
||||
$this->xmlWriter->startElement('radialGradient');
|
||||
} else {
|
||||
$this->xmlWriter->startElement('linearGradient');
|
||||
}
|
||||
|
||||
$this->xmlWriter->writeAttribute('gradientUnits', 'userSpaceOnUse');
|
||||
|
||||
switch ($gradient->getType()) {
|
||||
case GradientType::HORIZONTAL():
|
||||
$this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('y1', (string) round($y, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('x2', (string) round($x + $width, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('y2', (string) round($y, self::PRECISION));
|
||||
break;
|
||||
|
||||
case GradientType::VERTICAL():
|
||||
$this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('y1', (string) round($y, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('x2', (string) round($x, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('y2', (string) round($y + $height, self::PRECISION));
|
||||
break;
|
||||
|
||||
case GradientType::DIAGONAL():
|
||||
$this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('y1', (string) round($y, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('x2', (string) round($x + $width, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('y2', (string) round($y + $height, self::PRECISION));
|
||||
break;
|
||||
|
||||
case GradientType::INVERSE_DIAGONAL():
|
||||
$this->xmlWriter->writeAttribute('x1', (string) round($x, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('y1', (string) round($y + $height, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('x2', (string) round($x + $width, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('y2', (string) round($y, self::PRECISION));
|
||||
break;
|
||||
|
||||
case GradientType::RADIAL():
|
||||
$this->xmlWriter->writeAttribute('cx', (string) round(($x + $width) / 2, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('cy', (string) round(($y + $height) / 2, self::PRECISION));
|
||||
$this->xmlWriter->writeAttribute('r', (string) round(max($width, $height) / 2, self::PRECISION));
|
||||
break;
|
||||
}
|
||||
|
||||
$id = sprintf('g%d', ++$this->gradientCount);
|
||||
$this->xmlWriter->writeAttribute('id', $id);
|
||||
|
||||
$this->xmlWriter->startElement('stop');
|
||||
$this->xmlWriter->writeAttribute('offset', '0%');
|
||||
$this->xmlWriter->writeAttribute('stop-color', $this->getColorString($startColor));
|
||||
|
||||
if ($startColor instanceof Alpha) {
|
||||
$this->xmlWriter->writeAttribute('stop-opacity', (string) $startColor->getAlpha());
|
||||
}
|
||||
|
||||
$this->xmlWriter->endElement();
|
||||
|
||||
$this->xmlWriter->startElement('stop');
|
||||
$this->xmlWriter->writeAttribute('offset', '100%');
|
||||
$this->xmlWriter->writeAttribute('stop-color', $this->getColorString($endColor));
|
||||
|
||||
if ($endColor instanceof Alpha) {
|
||||
$this->xmlWriter->writeAttribute('stop-opacity', (string) $endColor->getAlpha());
|
||||
}
|
||||
|
||||
$this->xmlWriter->endElement();
|
||||
|
||||
$this->xmlWriter->endElement();
|
||||
$this->xmlWriter->endElement();
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
private function getColorString(ColorInterface $color) : string
|
||||
{
|
||||
$color = $color->toRgb();
|
||||
|
||||
return sprintf(
|
||||
'#%02x%02x%02x',
|
||||
$color->getRed(),
|
||||
$color->getGreen(),
|
||||
$color->getBlue()
|
||||
);
|
||||
}
|
||||
}
|
68
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php
vendored
Normal file
68
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Image/TransformationMatrix.php
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Image;
|
||||
|
||||
final class TransformationMatrix
|
||||
{
|
||||
/**
|
||||
* @var float[]
|
||||
*/
|
||||
private $values;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->values = [1, 0, 0, 1, 0, 0];
|
||||
}
|
||||
|
||||
public function multiply(self $other) : self
|
||||
{
|
||||
$matrix = new self();
|
||||
$matrix->values[0] = $this->values[0] * $other->values[0] + $this->values[2] * $other->values[1];
|
||||
$matrix->values[1] = $this->values[1] * $other->values[0] + $this->values[3] * $other->values[1];
|
||||
$matrix->values[2] = $this->values[0] * $other->values[2] + $this->values[2] * $other->values[3];
|
||||
$matrix->values[3] = $this->values[1] * $other->values[2] + $this->values[3] * $other->values[3];
|
||||
$matrix->values[4] = $this->values[0] * $other->values[4] + $this->values[2] * $other->values[5]
|
||||
+ $this->values[4];
|
||||
$matrix->values[5] = $this->values[1] * $other->values[4] + $this->values[3] * $other->values[5]
|
||||
+ $this->values[5];
|
||||
|
||||
return $matrix;
|
||||
}
|
||||
|
||||
public static function scale(float $size) : self
|
||||
{
|
||||
$matrix = new self();
|
||||
$matrix->values = [$size, 0, 0, $size, 0, 0];
|
||||
return $matrix;
|
||||
}
|
||||
|
||||
public static function translate(float $x, float $y) : self
|
||||
{
|
||||
$matrix = new self();
|
||||
$matrix->values = [1, 0, 0, 1, $x, $y];
|
||||
return $matrix;
|
||||
}
|
||||
|
||||
public static function rotate(int $degrees) : self
|
||||
{
|
||||
$matrix = new self();
|
||||
$rad = deg2rad($degrees);
|
||||
$matrix->values = [cos($rad), sin($rad), -sin($rad), cos($rad), 0, 0];
|
||||
return $matrix;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Applies this matrix onto a point and returns the resulting viewport point.
|
||||
*
|
||||
* @return float[]
|
||||
*/
|
||||
public function apply(float $x, float $y) : array
|
||||
{
|
||||
return [
|
||||
$x * $this->values[0] + $y * $this->values[2] + $this->values[4],
|
||||
$x * $this->values[1] + $y * $this->values[3] + $this->values[5],
|
||||
];
|
||||
}
|
||||
}
|
152
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php
vendored
Normal file
152
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/ImageRenderer.php
vendored
Normal file
|
@ -0,0 +1,152 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer;
|
||||
|
||||
use BaconQrCode\Encoder\MatrixUtil;
|
||||
use BaconQrCode\Encoder\QrCode;
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
use BaconQrCode\Renderer\Image\ImageBackEndInterface;
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
use BaconQrCode\Renderer\RendererStyle\EyeFill;
|
||||
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
|
||||
|
||||
final class ImageRenderer implements RendererInterface
|
||||
{
|
||||
/**
|
||||
* @var RendererStyle
|
||||
*/
|
||||
private $rendererStyle;
|
||||
|
||||
/**
|
||||
* @var ImageBackEndInterface
|
||||
*/
|
||||
private $imageBackEnd;
|
||||
|
||||
public function __construct(RendererStyle $rendererStyle, ImageBackEndInterface $imageBackEnd)
|
||||
{
|
||||
$this->rendererStyle = $rendererStyle;
|
||||
$this->imageBackEnd = $imageBackEnd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if matrix width doesn't match height
|
||||
*/
|
||||
public function render(QrCode $qrCode) : string
|
||||
{
|
||||
$size = $this->rendererStyle->getSize();
|
||||
$margin = $this->rendererStyle->getMargin();
|
||||
$matrix = $qrCode->getMatrix();
|
||||
$matrixSize = $matrix->getWidth();
|
||||
|
||||
if ($matrixSize !== $matrix->getHeight()) {
|
||||
throw new InvalidArgumentException('Matrix must have the same width and height');
|
||||
}
|
||||
|
||||
$totalSize = $matrixSize + ($margin * 2);
|
||||
$moduleSize = $size / $totalSize;
|
||||
$fill = $this->rendererStyle->getFill();
|
||||
|
||||
$this->imageBackEnd->new($size, $fill->getBackgroundColor());
|
||||
$this->imageBackEnd->scale((float) $moduleSize);
|
||||
$this->imageBackEnd->translate((float) $margin, (float) $margin);
|
||||
|
||||
$module = $this->rendererStyle->getModule();
|
||||
$moduleMatrix = clone $matrix;
|
||||
MatrixUtil::removePositionDetectionPatterns($moduleMatrix);
|
||||
$modulePath = $this->drawEyes($matrixSize, $module->createPath($moduleMatrix));
|
||||
|
||||
if ($fill->hasGradientFill()) {
|
||||
$this->imageBackEnd->drawPathWithGradient(
|
||||
$modulePath,
|
||||
$fill->getForegroundGradient(),
|
||||
0,
|
||||
0,
|
||||
$matrixSize,
|
||||
$matrixSize
|
||||
);
|
||||
} else {
|
||||
$this->imageBackEnd->drawPathWithColor($modulePath, $fill->getForegroundColor());
|
||||
}
|
||||
|
||||
return $this->imageBackEnd->done();
|
||||
}
|
||||
|
||||
private function drawEyes(int $matrixSize, Path $modulePath) : Path
|
||||
{
|
||||
$fill = $this->rendererStyle->getFill();
|
||||
|
||||
$eye = $this->rendererStyle->getEye();
|
||||
$externalPath = $eye->getExternalPath();
|
||||
$internalPath = $eye->getInternalPath();
|
||||
|
||||
$modulePath = $this->drawEye(
|
||||
$externalPath,
|
||||
$internalPath,
|
||||
$fill->getTopLeftEyeFill(),
|
||||
3.5,
|
||||
3.5,
|
||||
0,
|
||||
$modulePath
|
||||
);
|
||||
$modulePath = $this->drawEye(
|
||||
$externalPath,
|
||||
$internalPath,
|
||||
$fill->getTopRightEyeFill(),
|
||||
$matrixSize - 3.5,
|
||||
3.5,
|
||||
90,
|
||||
$modulePath
|
||||
);
|
||||
$modulePath = $this->drawEye(
|
||||
$externalPath,
|
||||
$internalPath,
|
||||
$fill->getBottomLeftEyeFill(),
|
||||
3.5,
|
||||
$matrixSize - 3.5,
|
||||
-90,
|
||||
$modulePath
|
||||
);
|
||||
|
||||
return $modulePath;
|
||||
}
|
||||
|
||||
private function drawEye(
|
||||
Path $externalPath,
|
||||
Path $internalPath,
|
||||
EyeFill $fill,
|
||||
float $xTranslation,
|
||||
float $yTranslation,
|
||||
int $rotation,
|
||||
Path $modulePath
|
||||
) : Path {
|
||||
if ($fill->inheritsBothColors()) {
|
||||
return $modulePath
|
||||
->append($externalPath->translate($xTranslation, $yTranslation))
|
||||
->append($internalPath->translate($xTranslation, $yTranslation));
|
||||
}
|
||||
|
||||
$this->imageBackEnd->push();
|
||||
$this->imageBackEnd->translate($xTranslation, $yTranslation);
|
||||
|
||||
if (0 !== $rotation) {
|
||||
$this->imageBackEnd->rotate($rotation);
|
||||
}
|
||||
|
||||
if ($fill->inheritsExternalColor()) {
|
||||
$modulePath = $modulePath->append($externalPath->translate($xTranslation, $yTranslation));
|
||||
} else {
|
||||
$this->imageBackEnd->drawPathWithColor($externalPath, $fill->getExternalColor());
|
||||
}
|
||||
|
||||
if ($fill->inheritsInternalColor()) {
|
||||
$modulePath = $modulePath->append($internalPath->translate($xTranslation, $yTranslation));
|
||||
} else {
|
||||
$this->imageBackEnd->drawPathWithColor($internalPath, $fill->getInternalColor());
|
||||
}
|
||||
|
||||
$this->imageBackEnd->pop();
|
||||
|
||||
return $modulePath;
|
||||
}
|
||||
}
|
63
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php
vendored
Normal file
63
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/DotsModule.php
vendored
Normal file
|
@ -0,0 +1,63 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Module;
|
||||
|
||||
use BaconQrCode\Encoder\ByteMatrix;
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
|
||||
/**
|
||||
* Renders individual modules as dots.
|
||||
*/
|
||||
final class DotsModule implements ModuleInterface
|
||||
{
|
||||
public const LARGE = 1;
|
||||
public const MEDIUM = .8;
|
||||
public const SMALL = .6;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $size;
|
||||
|
||||
public function __construct(float $size)
|
||||
{
|
||||
if ($size <= 0 || $size > 1) {
|
||||
throw new InvalidArgumentException('Size must between 0 (exclusive) and 1 (inclusive)');
|
||||
}
|
||||
|
||||
$this->size = $size;
|
||||
}
|
||||
|
||||
public function createPath(ByteMatrix $matrix) : Path
|
||||
{
|
||||
$width = $matrix->getWidth();
|
||||
$height = $matrix->getHeight();
|
||||
$path = new Path();
|
||||
$halfSize = $this->size / 2;
|
||||
$margin = (1 - $this->size) / 2;
|
||||
|
||||
for ($y = 0; $y < $height; ++$y) {
|
||||
for ($x = 0; $x < $width; ++$x) {
|
||||
if (! $matrix->get($x, $y)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$pathX = $x + $margin;
|
||||
$pathY = $y + $margin;
|
||||
|
||||
$path = $path
|
||||
->move($pathX + $this->size, $pathY + $halfSize)
|
||||
->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX + $halfSize, $pathY + $this->size)
|
||||
->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX, $pathY + $halfSize)
|
||||
->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX + $halfSize, $pathY)
|
||||
->ellipticArc($halfSize, $halfSize, 0, false, true, $pathX + $this->size, $pathY + $halfSize)
|
||||
->close()
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
}
|
100
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php
vendored
Normal file
100
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/Edge.php
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Module\EdgeIterator;
|
||||
|
||||
final class Edge
|
||||
{
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $positive;
|
||||
|
||||
/**
|
||||
* @var array<int[]>
|
||||
*/
|
||||
private $points = [];
|
||||
|
||||
/**
|
||||
* @var array<int[]>|null
|
||||
*/
|
||||
private $simplifiedPoints;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $minX = PHP_INT_MAX;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $minY = PHP_INT_MAX;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $maxX = -1;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $maxY = -1;
|
||||
|
||||
public function __construct(bool $positive)
|
||||
{
|
||||
$this->positive = $positive;
|
||||
}
|
||||
|
||||
public function addPoint(int $x, int $y) : void
|
||||
{
|
||||
$this->points[] = [$x, $y];
|
||||
$this->minX = min($this->minX, $x);
|
||||
$this->minY = min($this->minY, $y);
|
||||
$this->maxX = max($this->maxX, $x);
|
||||
$this->maxY = max($this->maxY, $y);
|
||||
}
|
||||
|
||||
public function isPositive() : bool
|
||||
{
|
||||
return $this->positive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int[]>
|
||||
*/
|
||||
public function getPoints() : array
|
||||
{
|
||||
return $this->points;
|
||||
}
|
||||
|
||||
public function getMaxX() : int
|
||||
{
|
||||
return $this->maxX;
|
||||
}
|
||||
|
||||
public function getSimplifiedPoints() : array
|
||||
{
|
||||
if (null !== $this->simplifiedPoints) {
|
||||
return $this->simplifiedPoints;
|
||||
}
|
||||
|
||||
$points = [];
|
||||
$length = count($this->points);
|
||||
|
||||
for ($i = 0; $i < $length; ++$i) {
|
||||
$previousPoint = $this->points[(0 === $i ? $length : $i) - 1];
|
||||
$nextPoint = $this->points[($length - 1 === $i ? -1 : $i) + 1];
|
||||
$currentPoint = $this->points[$i];
|
||||
|
||||
if (($previousPoint[0] === $currentPoint[0] && $currentPoint[0] === $nextPoint[0])
|
||||
|| ($previousPoint[1] === $currentPoint[1] && $currentPoint[1] === $nextPoint[1])
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$points[] = $currentPoint;
|
||||
}
|
||||
|
||||
return $this->simplifiedPoints = $points;
|
||||
}
|
||||
}
|
169
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php
vendored
Normal file
169
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/EdgeIterator/EdgeIterator.php
vendored
Normal file
|
@ -0,0 +1,169 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Module\EdgeIterator;
|
||||
|
||||
use BaconQrCode\Encoder\ByteMatrix;
|
||||
use IteratorAggregate;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* Edge iterator based on potrace.
|
||||
*/
|
||||
final class EdgeIterator implements IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var int[]
|
||||
*/
|
||||
private $bytes = [];
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $size;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $width;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $height;
|
||||
|
||||
public function __construct(ByteMatrix $matrix)
|
||||
{
|
||||
$this->bytes = iterator_to_array($matrix->getBytes());
|
||||
$this->size = count($this->bytes);
|
||||
$this->width = $matrix->getWidth();
|
||||
$this->height = $matrix->getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Traversable<Edge>
|
||||
*/
|
||||
public function getIterator() : Traversable
|
||||
{
|
||||
$originalBytes = $this->bytes;
|
||||
$point = $this->findNext(0, 0);
|
||||
|
||||
while (null !== $point) {
|
||||
$edge = $this->findEdge($point[0], $point[1]);
|
||||
$this->xorEdge($edge);
|
||||
|
||||
yield $edge;
|
||||
|
||||
$point = $this->findNext($point[0], $point[1]);
|
||||
}
|
||||
|
||||
$this->bytes = $originalBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]|null
|
||||
*/
|
||||
private function findNext(int $x, int $y) : ?array
|
||||
{
|
||||
$i = $this->width * $y + $x;
|
||||
|
||||
while ($i < $this->size && 1 !== $this->bytes[$i]) {
|
||||
++$i;
|
||||
}
|
||||
|
||||
if ($i < $this->size) {
|
||||
return $this->pointOf($i);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private function findEdge(int $x, int $y) : Edge
|
||||
{
|
||||
$edge = new Edge($this->isSet($x, $y));
|
||||
$startX = $x;
|
||||
$startY = $y;
|
||||
$dirX = 0;
|
||||
$dirY = 1;
|
||||
|
||||
while (true) {
|
||||
$edge->addPoint($x, $y);
|
||||
$x += $dirX;
|
||||
$y += $dirY;
|
||||
|
||||
if ($x === $startX && $y === $startY) {
|
||||
break;
|
||||
}
|
||||
|
||||
$left = $this->isSet($x + ($dirX + $dirY - 1 ) / 2, $y + ($dirY - $dirX - 1) / 2);
|
||||
$right = $this->isSet($x + ($dirX - $dirY - 1) / 2, $y + ($dirY + $dirX - 1) / 2);
|
||||
|
||||
if ($right && ! $left) {
|
||||
$tmp = $dirX;
|
||||
$dirX = -$dirY;
|
||||
$dirY = $tmp;
|
||||
} elseif ($right) {
|
||||
$tmp = $dirX;
|
||||
$dirX = -$dirY;
|
||||
$dirY = $tmp;
|
||||
} elseif (! $left) {
|
||||
$tmp = $dirX;
|
||||
$dirX = $dirY;
|
||||
$dirY = -$tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return $edge;
|
||||
}
|
||||
|
||||
private function xorEdge(Edge $path) : void
|
||||
{
|
||||
$points = $path->getPoints();
|
||||
$y1 = $points[0][1];
|
||||
$length = count($points);
|
||||
$maxX = $path->getMaxX();
|
||||
|
||||
for ($i = 1; $i < $length; ++$i) {
|
||||
$y = $points[$i][1];
|
||||
|
||||
if ($y === $y1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$x = $points[$i][0];
|
||||
$minY = min($y1, $y);
|
||||
|
||||
for ($j = $x; $j < $maxX; ++$j) {
|
||||
$this->flip($j, $minY);
|
||||
}
|
||||
|
||||
$y1 = $y;
|
||||
}
|
||||
}
|
||||
|
||||
private function isSet(int $x, int $y) : bool
|
||||
{
|
||||
return (
|
||||
$x >= 0
|
||||
&& $x < $this->width
|
||||
&& $y >= 0
|
||||
&& $y < $this->height
|
||||
) && 1 === $this->bytes[$this->width * $y + $x];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int[]
|
||||
*/
|
||||
private function pointOf(int $i) : array
|
||||
{
|
||||
$y = intdiv($i, $this->width);
|
||||
return [$i - $y * $this->width, $y];
|
||||
}
|
||||
|
||||
private function flip(int $x, int $y) : void
|
||||
{
|
||||
$this->bytes[$this->width * $y + $x] = (
|
||||
$this->isSet($x, $y) ? 0 : 1
|
||||
);
|
||||
}
|
||||
}
|
18
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php
vendored
Normal file
18
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/ModuleInterface.php
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Module;
|
||||
|
||||
use BaconQrCode\Encoder\ByteMatrix;
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
|
||||
/**
|
||||
* Interface describing how modules should be rendered.
|
||||
*
|
||||
* A module always receives a byte matrix (with values either being 1 or 0). It returns a path, where the origin
|
||||
* coordinate (0, 0) equals the top left corner of the first matrix value.
|
||||
*/
|
||||
interface ModuleInterface
|
||||
{
|
||||
public function createPath(ByteMatrix $matrix) : Path;
|
||||
}
|
129
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/RoundnessModule.php
vendored
Normal file
129
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/RoundnessModule.php
vendored
Normal file
|
@ -0,0 +1,129 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Module;
|
||||
|
||||
use BaconQrCode\Encoder\ByteMatrix;
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
use BaconQrCode\Renderer\Module\EdgeIterator\EdgeIterator;
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
|
||||
/**
|
||||
* Rounds the corners of module groups.
|
||||
*/
|
||||
final class RoundnessModule implements ModuleInterface
|
||||
{
|
||||
public const STRONG = 1;
|
||||
public const MEDIUM = .5;
|
||||
public const SOFT = .25;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $intensity;
|
||||
|
||||
public function __construct(float $intensity)
|
||||
{
|
||||
if ($intensity <= 0 || $intensity > 1) {
|
||||
throw new InvalidArgumentException('Intensity must between 0 (exclusive) and 1 (inclusive)');
|
||||
}
|
||||
|
||||
$this->intensity = $intensity / 2;
|
||||
}
|
||||
|
||||
public function createPath(ByteMatrix $matrix) : Path
|
||||
{
|
||||
$path = new Path();
|
||||
|
||||
foreach (new EdgeIterator($matrix) as $edge) {
|
||||
$points = $edge->getSimplifiedPoints();
|
||||
$length = count($points);
|
||||
|
||||
$currentPoint = $points[0];
|
||||
$nextPoint = $points[1];
|
||||
$horizontal = ($currentPoint[1] === $nextPoint[1]);
|
||||
|
||||
if ($horizontal) {
|
||||
$right = $nextPoint[0] > $currentPoint[0];
|
||||
$path = $path->move(
|
||||
$currentPoint[0] + ($right ? $this->intensity : -$this->intensity),
|
||||
$currentPoint[1]
|
||||
);
|
||||
} else {
|
||||
$up = $nextPoint[0] < $currentPoint[0];
|
||||
$path = $path->move(
|
||||
$currentPoint[0],
|
||||
$currentPoint[1] + ($up ? -$this->intensity : $this->intensity)
|
||||
);
|
||||
}
|
||||
|
||||
for ($i = 1; $i <= $length; ++$i) {
|
||||
if ($i === $length) {
|
||||
$previousPoint = $points[$length - 1];
|
||||
$currentPoint = $points[0];
|
||||
$nextPoint = $points[1];
|
||||
} else {
|
||||
$previousPoint = $points[(0 === $i ? $length : $i) - 1];
|
||||
$currentPoint = $points[$i];
|
||||
$nextPoint = $points[($length - 1 === $i ? -1 : $i) + 1];
|
||||
}
|
||||
|
||||
$horizontal = ($previousPoint[1] === $currentPoint[1]);
|
||||
|
||||
if ($horizontal) {
|
||||
$right = $previousPoint[0] < $currentPoint[0];
|
||||
$up = $nextPoint[1] < $currentPoint[1];
|
||||
$sweep = ($up xor $right);
|
||||
|
||||
if ($this->intensity < 0.5
|
||||
|| ($right && $previousPoint[0] !== $currentPoint[0] - 1)
|
||||
|| (! $right && $previousPoint[0] - 1 !== $currentPoint[0])
|
||||
) {
|
||||
$path = $path->line(
|
||||
$currentPoint[0] + ($right ? -$this->intensity : $this->intensity),
|
||||
$currentPoint[1]
|
||||
);
|
||||
}
|
||||
|
||||
$path = $path->ellipticArc(
|
||||
$this->intensity,
|
||||
$this->intensity,
|
||||
0,
|
||||
false,
|
||||
$sweep,
|
||||
$currentPoint[0],
|
||||
$currentPoint[1] + ($up ? -$this->intensity : $this->intensity)
|
||||
);
|
||||
} else {
|
||||
$up = $previousPoint[1] > $currentPoint[1];
|
||||
$right = $nextPoint[0] > $currentPoint[0];
|
||||
$sweep = ! ($up xor $right);
|
||||
|
||||
if ($this->intensity < 0.5
|
||||
|| ($up && $previousPoint[1] !== $currentPoint[1] + 1)
|
||||
|| (! $up && $previousPoint[0] + 1 !== $currentPoint[0])
|
||||
) {
|
||||
$path = $path->line(
|
||||
$currentPoint[0],
|
||||
$currentPoint[1] + ($up ? $this->intensity : -$this->intensity)
|
||||
);
|
||||
}
|
||||
|
||||
$path = $path->ellipticArc(
|
||||
$this->intensity,
|
||||
$this->intensity,
|
||||
0,
|
||||
false,
|
||||
$sweep,
|
||||
$currentPoint[0] + ($right ? $this->intensity : -$this->intensity),
|
||||
$currentPoint[1]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$path = $path->close();
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
}
|
47
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php
vendored
Normal file
47
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Module/SquareModule.php
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Module;
|
||||
|
||||
use BaconQrCode\Encoder\ByteMatrix;
|
||||
use BaconQrCode\Renderer\Module\EdgeIterator\EdgeIterator;
|
||||
use BaconQrCode\Renderer\Path\Path;
|
||||
|
||||
/**
|
||||
* Groups modules together to a single path.
|
||||
*/
|
||||
final class SquareModule implements ModuleInterface
|
||||
{
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function instance() : self
|
||||
{
|
||||
return self::$instance ?: self::$instance = new self();
|
||||
}
|
||||
|
||||
public function createPath(ByteMatrix $matrix) : Path
|
||||
{
|
||||
$path = new Path();
|
||||
|
||||
foreach (new EdgeIterator($matrix) as $edge) {
|
||||
$points = $edge->getSimplifiedPoints();
|
||||
$length = count($points);
|
||||
$path = $path->move($points[0][0], $points[0][1]);
|
||||
|
||||
for ($i = 1; $i < $length; ++$i) {
|
||||
$path = $path->line($points[$i][0], $points[$i][1]);
|
||||
}
|
||||
|
||||
$path = $path->close();
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
}
|
29
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/Close.php
vendored
Normal file
29
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/Close.php
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
final class Close implements OperationInterface
|
||||
{
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public static function instance() : self
|
||||
{
|
||||
return self::$instance ?: self::$instance = new self();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function translate(float $x, float $y) : OperationInterface
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
}
|
92
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/Curve.php
vendored
Normal file
92
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/Curve.php
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
final class Curve implements OperationInterface
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x1;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y1;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x2;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y2;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x3;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y3;
|
||||
|
||||
public function __construct(float $x1, float $y1, float $x2, float $y2, float $x3, float $y3)
|
||||
{
|
||||
$this->x1 = $x1;
|
||||
$this->y1 = $y1;
|
||||
$this->x2 = $x2;
|
||||
$this->y2 = $y2;
|
||||
$this->x3 = $x3;
|
||||
$this->y3 = $y3;
|
||||
}
|
||||
|
||||
public function getX1() : float
|
||||
{
|
||||
return $this->x1;
|
||||
}
|
||||
|
||||
public function getY1() : float
|
||||
{
|
||||
return $this->y1;
|
||||
}
|
||||
|
||||
public function getX2() : float
|
||||
{
|
||||
return $this->x2;
|
||||
}
|
||||
|
||||
public function getY2() : float
|
||||
{
|
||||
return $this->y2;
|
||||
}
|
||||
|
||||
public function getX3() : float
|
||||
{
|
||||
return $this->x3;
|
||||
}
|
||||
|
||||
public function getY3() : float
|
||||
{
|
||||
return $this->y3;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function translate(float $x, float $y) : OperationInterface
|
||||
{
|
||||
return new self(
|
||||
$this->x1 + $x,
|
||||
$this->y1 + $y,
|
||||
$this->x2 + $x,
|
||||
$this->y2 + $y,
|
||||
$this->x3 + $x,
|
||||
$this->y3 + $y
|
||||
);
|
||||
}
|
||||
}
|
278
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php
vendored
Normal file
278
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/EllipticArc.php
vendored
Normal file
|
@ -0,0 +1,278 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
final class EllipticArc implements OperationInterface
|
||||
{
|
||||
private const ZERO_TOLERANCE = 1e-05;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $xRadius;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $yRadius;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $xAxisAngle;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $largeArc;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $sweep;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y;
|
||||
|
||||
public function __construct(
|
||||
float $xRadius,
|
||||
float $yRadius,
|
||||
float $xAxisAngle,
|
||||
bool $largeArc,
|
||||
bool $sweep,
|
||||
float $x,
|
||||
float $y
|
||||
) {
|
||||
$this->xRadius = abs($xRadius);
|
||||
$this->yRadius = abs($yRadius);
|
||||
$this->xAxisAngle = $xAxisAngle % 360;
|
||||
$this->largeArc = $largeArc;
|
||||
$this->sweep = $sweep;
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
}
|
||||
|
||||
public function getXRadius() : float
|
||||
{
|
||||
return $this->xRadius;
|
||||
}
|
||||
|
||||
public function getYRadius() : float
|
||||
{
|
||||
return $this->yRadius;
|
||||
}
|
||||
|
||||
public function getXAxisAngle() : float
|
||||
{
|
||||
return $this->xAxisAngle;
|
||||
}
|
||||
|
||||
public function isLargeArc() : bool
|
||||
{
|
||||
return $this->largeArc;
|
||||
}
|
||||
|
||||
public function isSweep() : bool
|
||||
{
|
||||
return $this->sweep;
|
||||
}
|
||||
|
||||
public function getX() : float
|
||||
{
|
||||
return $this->x;
|
||||
}
|
||||
|
||||
public function getY() : float
|
||||
{
|
||||
return $this->y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function translate(float $x, float $y) : OperationInterface
|
||||
{
|
||||
return new self(
|
||||
$this->xRadius,
|
||||
$this->yRadius,
|
||||
$this->xAxisAngle,
|
||||
$this->largeArc,
|
||||
$this->sweep,
|
||||
$this->x + $x,
|
||||
$this->y + $y
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the elliptic arc to multiple curves.
|
||||
*
|
||||
* Since not all image back ends support elliptic arcs, this method allows to convert the arc into multiple curves
|
||||
* resembling the same result.
|
||||
*
|
||||
* @see https://mortoray.com/2017/02/16/rendering-an-svg-elliptical-arc-as-bezier-curves/
|
||||
* @return array<Curve|Line>
|
||||
*/
|
||||
public function toCurves(float $fromX, float $fromY) : array
|
||||
{
|
||||
if (sqrt(($fromX - $this->x) ** 2 + ($fromY - $this->y) ** 2) < self::ZERO_TOLERANCE) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if ($this->xRadius < self::ZERO_TOLERANCE || $this->yRadius < self::ZERO_TOLERANCE) {
|
||||
return [new Line($this->x, $this->y)];
|
||||
}
|
||||
|
||||
return $this->createCurves($fromX, $fromY);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Curve[]
|
||||
*/
|
||||
private function createCurves(float $fromX, float $fromY) : array
|
||||
{
|
||||
$xAngle = deg2rad($this->xAxisAngle);
|
||||
list($centerX, $centerY, $radiusX, $radiusY, $startAngle, $deltaAngle) =
|
||||
$this->calculateCenterPointParameters($fromX, $fromY, $xAngle);
|
||||
|
||||
$s = $startAngle;
|
||||
$e = $s + $deltaAngle;
|
||||
$sign = ($e < $s) ? -1 : 1;
|
||||
$remain = abs($e - $s);
|
||||
$p1 = self::point($centerX, $centerY, $radiusX, $radiusY, $xAngle, $s);
|
||||
$curves = [];
|
||||
|
||||
while ($remain > self::ZERO_TOLERANCE) {
|
||||
$step = min($remain, pi() / 2);
|
||||
$signStep = $step * $sign;
|
||||
$p2 = self::point($centerX, $centerY, $radiusX, $radiusY, $xAngle, $s + $signStep);
|
||||
|
||||
$alphaT = tan($signStep / 2);
|
||||
$alpha = sin($signStep) * (sqrt(4 + 3 * $alphaT ** 2) - 1) / 3;
|
||||
$d1 = self::derivative($radiusX, $radiusY, $xAngle, $s);
|
||||
$d2 = self::derivative($radiusX, $radiusY, $xAngle, $s + $signStep);
|
||||
|
||||
$curves[] = new Curve(
|
||||
$p1[0] + $alpha * $d1[0],
|
||||
$p1[1] + $alpha * $d1[1],
|
||||
$p2[0] - $alpha * $d2[0],
|
||||
$p2[1] - $alpha * $d2[1],
|
||||
$p2[0],
|
||||
$p2[1]
|
||||
);
|
||||
|
||||
$s += $signStep;
|
||||
$remain -= $step;
|
||||
$p1 = $p2;
|
||||
}
|
||||
|
||||
return $curves;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float[]
|
||||
*/
|
||||
private function calculateCenterPointParameters(float $fromX, float $fromY, float $xAngle)
|
||||
{
|
||||
$rX = $this->xRadius;
|
||||
$rY = $this->yRadius;
|
||||
|
||||
// F.6.5.1
|
||||
$dx2 = ($fromX - $this->x) / 2;
|
||||
$dy2 = ($fromY - $this->y) / 2;
|
||||
$x1p = cos($xAngle) * $dx2 + sin($xAngle) * $dy2;
|
||||
$y1p = -sin($xAngle) * $dx2 + cos($xAngle) * $dy2;
|
||||
|
||||
// F.6.5.2
|
||||
$rxs = $rX ** 2;
|
||||
$rys = $rY ** 2;
|
||||
$x1ps = $x1p ** 2;
|
||||
$y1ps = $y1p ** 2;
|
||||
$cr = $x1ps / $rxs + $y1ps / $rys;
|
||||
|
||||
if ($cr > 1) {
|
||||
$s = sqrt($cr);
|
||||
$rX *= $s;
|
||||
$rY *= $s;
|
||||
$rxs = $rX ** 2;
|
||||
$rys = $rY ** 2;
|
||||
}
|
||||
|
||||
$dq = ($rxs * $y1ps + $rys * $x1ps);
|
||||
$pq = ($rxs * $rys - $dq) / $dq;
|
||||
$q = sqrt(max(0, $pq));
|
||||
|
||||
if ($this->largeArc === $this->sweep) {
|
||||
$q = -$q;
|
||||
}
|
||||
|
||||
$cxp = $q * $rX * $y1p / $rY;
|
||||
$cyp = -$q * $rY * $x1p / $rX;
|
||||
|
||||
// F.6.5.3
|
||||
$cx = cos($xAngle) * $cxp - sin($xAngle) * $cyp + ($fromX + $this->x) / 2;
|
||||
$cy = sin($xAngle) * $cxp + cos($xAngle) * $cyp + ($fromY + $this->y) / 2;
|
||||
|
||||
// F.6.5.5
|
||||
$theta = self::angle(1, 0, ($x1p - $cxp) / $rX, ($y1p - $cyp) / $rY);
|
||||
|
||||
// F.6.5.6
|
||||
$delta = self::angle(($x1p - $cxp) / $rX, ($y1p - $cyp) / $rY, (-$x1p - $cxp) / $rX, (-$y1p - $cyp) / $rY);
|
||||
$delta = fmod($delta, pi() * 2);
|
||||
|
||||
if (! $this->sweep) {
|
||||
$delta -= 2 * pi();
|
||||
}
|
||||
|
||||
return [$cx, $cy, $rX, $rY, $theta, $delta];
|
||||
}
|
||||
|
||||
private static function angle(float $ux, float $uy, float $vx, float $vy) : float
|
||||
{
|
||||
// F.6.5.4
|
||||
$dot = $ux * $vx + $uy * $vy;
|
||||
$length = sqrt($ux ** 2 + $uy ** 2) * sqrt($vx ** 2 + $vy ** 2);
|
||||
$angle = acos(min(1, max(-1, $dot / $length)));
|
||||
|
||||
if (($ux * $vy - $uy * $vx) < 0) {
|
||||
return -$angle;
|
||||
}
|
||||
|
||||
return $angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float[]
|
||||
*/
|
||||
private static function point(
|
||||
float $centerX,
|
||||
float $centerY,
|
||||
float $radiusX,
|
||||
float $radiusY,
|
||||
float $xAngle,
|
||||
float $angle
|
||||
) : array {
|
||||
return [
|
||||
$centerX + $radiusX * cos($xAngle) * cos($angle) - $radiusY * sin($xAngle) * sin($angle),
|
||||
$centerY + $radiusX * sin($xAngle) * cos($angle) + $radiusY * cos($xAngle) * sin($angle),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return float[]
|
||||
*/
|
||||
private static function derivative(float $radiusX, float $radiusY, float $xAngle, float $angle) : array
|
||||
{
|
||||
return [
|
||||
-$radiusX * cos($xAngle) * sin($angle) - $radiusY * sin($xAngle) * cos($angle),
|
||||
-$radiusX * sin($xAngle) * sin($angle) + $radiusY * cos($xAngle) * cos($angle),
|
||||
];
|
||||
}
|
||||
}
|
41
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/Line.php
vendored
Normal file
41
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/Line.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
final class Line implements OperationInterface
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y;
|
||||
|
||||
public function __construct(float $x, float $y)
|
||||
{
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
}
|
||||
|
||||
public function getX() : float
|
||||
{
|
||||
return $this->x;
|
||||
}
|
||||
|
||||
public function getY() : float
|
||||
{
|
||||
return $this->y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function translate(float $x, float $y) : OperationInterface
|
||||
{
|
||||
return new self($this->x + $x, $this->y + $y);
|
||||
}
|
||||
}
|
41
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/Move.php
vendored
Normal file
41
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/Move.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
final class Move implements OperationInterface
|
||||
{
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $x;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $y;
|
||||
|
||||
public function __construct(float $x, float $y)
|
||||
{
|
||||
$this->x = $x;
|
||||
$this->y = $y;
|
||||
}
|
||||
|
||||
public function getX() : float
|
||||
{
|
||||
return $this->x;
|
||||
}
|
||||
|
||||
public function getY() : float
|
||||
{
|
||||
return $this->y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return self
|
||||
*/
|
||||
public function translate(float $x, float $y) : OperationInterface
|
||||
{
|
||||
return new self($this->x + $x, $this->y + $y);
|
||||
}
|
||||
}
|
12
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php
vendored
Normal file
12
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/OperationInterface.php
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
interface OperationInterface
|
||||
{
|
||||
/**
|
||||
* Translates the operation's coordinates.
|
||||
*/
|
||||
public function translate(float $x, float $y) : self;
|
||||
}
|
106
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/Path.php
vendored
Normal file
106
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/Path/Path.php
vendored
Normal file
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\Path;
|
||||
|
||||
use IteratorAggregate;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* Internal Representation of a vector path.
|
||||
*/
|
||||
final class Path implements IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var OperationInterface[]
|
||||
*/
|
||||
private $operations = [];
|
||||
|
||||
/**
|
||||
* Moves the drawing operation to a certain position.
|
||||
*/
|
||||
public function move(float $x, float $y) : self
|
||||
{
|
||||
$path = clone $this;
|
||||
$path->operations[] = new Move($x, $y);
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a line from the current position to another position.
|
||||
*/
|
||||
public function line(float $x, float $y) : self
|
||||
{
|
||||
$path = clone $this;
|
||||
$path->operations[] = new Line($x, $y);
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws an elliptic arc from the current position to another position.
|
||||
*/
|
||||
public function ellipticArc(
|
||||
float $xRadius,
|
||||
float $yRadius,
|
||||
float $xAxisRotation,
|
||||
bool $largeArc,
|
||||
bool $sweep,
|
||||
float $x,
|
||||
float $y
|
||||
) : self {
|
||||
$path = clone $this;
|
||||
$path->operations[] = new EllipticArc($xRadius, $yRadius, $xAxisRotation, $largeArc, $sweep, $x, $y);
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws a curve from the current position to another position.
|
||||
*/
|
||||
public function curve(float $x1, float $y1, float $x2, float $y2, float $x3, float $y3) : self
|
||||
{
|
||||
$path = clone $this;
|
||||
$path->operations[] = new Curve($x1, $y1, $x2, $y2, $x3, $y3);
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes a sub-path.
|
||||
*/
|
||||
public function close() : self
|
||||
{
|
||||
$path = clone $this;
|
||||
$path->operations[] = Close::instance();
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends another path to this one.
|
||||
*/
|
||||
public function append(self $other) : self
|
||||
{
|
||||
$path = clone $this;
|
||||
$path->operations = array_merge($this->operations, $other->operations);
|
||||
return $path;
|
||||
}
|
||||
|
||||
public function translate(float $x, float $y) : self
|
||||
{
|
||||
$path = new self();
|
||||
|
||||
foreach ($this->operations as $operation) {
|
||||
$path->operations[] = $operation->translate($x, $y);
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OperationInterface[]|Traversable
|
||||
*/
|
||||
public function getIterator() : Traversable
|
||||
{
|
||||
foreach ($this->operations as $operation) {
|
||||
yield $operation;
|
||||
}
|
||||
}
|
||||
}
|
86
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php
vendored
Normal file
86
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/PlainTextRenderer.php
vendored
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer;
|
||||
|
||||
use BaconQrCode\Encoder\QrCode;
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
|
||||
final class PlainTextRenderer implements RendererInterface
|
||||
{
|
||||
/**
|
||||
* UTF-8 full block (U+2588)
|
||||
*/
|
||||
private const FULL_BLOCK = "\xe2\x96\x88";
|
||||
|
||||
/**
|
||||
* UTF-8 upper half block (U+2580)
|
||||
*/
|
||||
private const UPPER_HALF_BLOCK = "\xe2\x96\x80";
|
||||
|
||||
/**
|
||||
* UTF-8 lower half block (U+2584)
|
||||
*/
|
||||
private const LOWER_HALF_BLOCK = "\xe2\x96\x84";
|
||||
|
||||
/**
|
||||
* UTF-8 no-break space (U+00A0)
|
||||
*/
|
||||
private const EMPTY_BLOCK = "\xc2\xa0";
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $margin;
|
||||
|
||||
public function __construct(int $margin = 2)
|
||||
{
|
||||
$this->margin = $margin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InvalidArgumentException if matrix width doesn't match height
|
||||
*/
|
||||
public function render(QrCode $qrCode) : string
|
||||
{
|
||||
$matrix = $qrCode->getMatrix();
|
||||
$matrixSize = $matrix->getWidth();
|
||||
|
||||
if ($matrixSize !== $matrix->getHeight()) {
|
||||
throw new InvalidArgumentException('Matrix must have the same width and height');
|
||||
}
|
||||
|
||||
$rows = $matrix->getArray()->toArray();
|
||||
|
||||
if (0 !== $matrixSize % 2) {
|
||||
$rows[] = array_fill(0, $matrixSize, 0);
|
||||
}
|
||||
|
||||
$horizontalMargin = str_repeat(self::EMPTY_BLOCK, $this->margin);
|
||||
$result = str_repeat("\n", (int) ceil($this->margin / 2));
|
||||
|
||||
for ($i = 0; $i < $matrixSize; $i += 2) {
|
||||
$result .= $horizontalMargin;
|
||||
|
||||
$upperRow = $rows[$i];
|
||||
$lowerRow = $rows[$i + 1];
|
||||
|
||||
for ($j = 0; $j < $matrixSize; ++$j) {
|
||||
$upperBit = $upperRow[$j];
|
||||
$lowerBit = $lowerRow[$j];
|
||||
|
||||
if ($upperBit) {
|
||||
$result .= $lowerBit ? self::FULL_BLOCK : self::UPPER_HALF_BLOCK;
|
||||
} else {
|
||||
$result .= $lowerBit ? self::LOWER_HALF_BLOCK : self::EMPTY_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
$result .= $horizontalMargin . "\n";
|
||||
}
|
||||
|
||||
$result .= str_repeat("\n", (int) ceil($this->margin / 2));
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
11
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererInterface.php
vendored
Normal file
11
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererInterface.php
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer;
|
||||
|
||||
use BaconQrCode\Encoder\QrCode;
|
||||
|
||||
interface RendererInterface
|
||||
{
|
||||
public function render(QrCode $qrCode) : string;
|
||||
}
|
74
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/EyeFill.php
vendored
Normal file
74
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/EyeFill.php
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\RendererStyle;
|
||||
|
||||
use BaconQrCode\Exception\RuntimeException;
|
||||
use BaconQrCode\Renderer\Color\ColorInterface;
|
||||
|
||||
final class EyeFill
|
||||
{
|
||||
/**
|
||||
* @var ColorInterface|null
|
||||
*/
|
||||
private $externalColor;
|
||||
|
||||
/**
|
||||
* @var ColorInterface|null
|
||||
*/
|
||||
private $internalColor;
|
||||
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $inherit;
|
||||
|
||||
public function __construct(?ColorInterface $externalColor, ?ColorInterface $internalColor)
|
||||
{
|
||||
$this->externalColor = $externalColor;
|
||||
$this->internalColor = $internalColor;
|
||||
}
|
||||
|
||||
public static function uniform(ColorInterface $color) : self
|
||||
{
|
||||
return new self($color, $color);
|
||||
}
|
||||
|
||||
public static function inherit() : self
|
||||
{
|
||||
return self::$inherit ?: self::$inherit = new self(null, null);
|
||||
}
|
||||
|
||||
public function inheritsBothColors() : bool
|
||||
{
|
||||
return null === $this->externalColor && null === $this->internalColor;
|
||||
}
|
||||
|
||||
public function inheritsExternalColor() : bool
|
||||
{
|
||||
return null === $this->externalColor;
|
||||
}
|
||||
|
||||
public function inheritsInternalColor() : bool
|
||||
{
|
||||
return null === $this->internalColor;
|
||||
}
|
||||
|
||||
public function getExternalColor() : ColorInterface
|
||||
{
|
||||
if (null === $this->externalColor) {
|
||||
throw new RuntimeException('External eye color inherits foreground color');
|
||||
}
|
||||
|
||||
return $this->externalColor;
|
||||
}
|
||||
|
||||
public function getInternalColor() : ColorInterface
|
||||
{
|
||||
if (null === $this->internalColor) {
|
||||
throw new RuntimeException('Internal eye color inherits foreground color');
|
||||
}
|
||||
|
||||
return $this->internalColor;
|
||||
}
|
||||
}
|
168
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php
vendored
Normal file
168
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Fill.php
vendored
Normal file
|
@ -0,0 +1,168 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\RendererStyle;
|
||||
|
||||
use BaconQrCode\Exception\RuntimeException;
|
||||
use BaconQrCode\Renderer\Color\ColorInterface;
|
||||
use BaconQrCode\Renderer\Color\Gray;
|
||||
|
||||
final class Fill
|
||||
{
|
||||
/**
|
||||
* @var ColorInterface
|
||||
*/
|
||||
private $backgroundColor;
|
||||
|
||||
/**
|
||||
* @var ColorInterface|null
|
||||
*/
|
||||
private $foregroundColor;
|
||||
|
||||
/**
|
||||
* @var Gradient|null
|
||||
*/
|
||||
private $foregroundGradient;
|
||||
|
||||
/**
|
||||
* @var EyeFill
|
||||
*/
|
||||
private $topLeftEyeFill;
|
||||
|
||||
/**
|
||||
* @var EyeFill
|
||||
*/
|
||||
private $topRightEyeFill;
|
||||
|
||||
/**
|
||||
* @var EyeFill
|
||||
*/
|
||||
private $bottomLeftEyeFill;
|
||||
|
||||
/**
|
||||
* @var self|null
|
||||
*/
|
||||
private static $default;
|
||||
|
||||
private function __construct(
|
||||
ColorInterface $backgroundColor,
|
||||
?ColorInterface $foregroundColor,
|
||||
?Gradient $foregroundGradient,
|
||||
EyeFill $topLeftEyeFill,
|
||||
EyeFill $topRightEyeFill,
|
||||
EyeFill $bottomLeftEyeFill
|
||||
) {
|
||||
$this->backgroundColor = $backgroundColor;
|
||||
$this->foregroundColor = $foregroundColor;
|
||||
$this->foregroundGradient = $foregroundGradient;
|
||||
$this->topLeftEyeFill = $topLeftEyeFill;
|
||||
$this->topRightEyeFill = $topRightEyeFill;
|
||||
$this->bottomLeftEyeFill = $bottomLeftEyeFill;
|
||||
}
|
||||
|
||||
public static function default() : self
|
||||
{
|
||||
return self::$default ?: self::$default = self::uniformColor(new Gray(100), new Gray(0));
|
||||
}
|
||||
|
||||
public static function withForegroundColor(
|
||||
ColorInterface $backgroundColor,
|
||||
ColorInterface $foregroundColor,
|
||||
EyeFill $topLeftEyeFill,
|
||||
EyeFill $topRightEyeFill,
|
||||
EyeFill $bottomLeftEyeFill
|
||||
) : self {
|
||||
return new self(
|
||||
$backgroundColor,
|
||||
$foregroundColor,
|
||||
null,
|
||||
$topLeftEyeFill,
|
||||
$topRightEyeFill,
|
||||
$bottomLeftEyeFill
|
||||
);
|
||||
}
|
||||
|
||||
public static function withForegroundGradient(
|
||||
ColorInterface $backgroundColor,
|
||||
Gradient $foregroundGradient,
|
||||
EyeFill $topLeftEyeFill,
|
||||
EyeFill $topRightEyeFill,
|
||||
EyeFill $bottomLeftEyeFill
|
||||
) : self {
|
||||
return new self(
|
||||
$backgroundColor,
|
||||
null,
|
||||
$foregroundGradient,
|
||||
$topLeftEyeFill,
|
||||
$topRightEyeFill,
|
||||
$bottomLeftEyeFill
|
||||
);
|
||||
}
|
||||
|
||||
public static function uniformColor(ColorInterface $backgroundColor, ColorInterface $foregroundColor) : self
|
||||
{
|
||||
return new self(
|
||||
$backgroundColor,
|
||||
$foregroundColor,
|
||||
null,
|
||||
EyeFill::inherit(),
|
||||
EyeFill::inherit(),
|
||||
EyeFill::inherit()
|
||||
);
|
||||
}
|
||||
|
||||
public static function uniformGradient(ColorInterface $backgroundColor, Gradient $foregroundGradient) : self
|
||||
{
|
||||
return new self(
|
||||
$backgroundColor,
|
||||
null,
|
||||
$foregroundGradient,
|
||||
EyeFill::inherit(),
|
||||
EyeFill::inherit(),
|
||||
EyeFill::inherit()
|
||||
);
|
||||
}
|
||||
|
||||
public function hasGradientFill() : bool
|
||||
{
|
||||
return null !== $this->foregroundGradient;
|
||||
}
|
||||
|
||||
public function getBackgroundColor() : ColorInterface
|
||||
{
|
||||
return $this->backgroundColor;
|
||||
}
|
||||
|
||||
public function getForegroundColor() : ColorInterface
|
||||
{
|
||||
if (null === $this->foregroundColor) {
|
||||
throw new RuntimeException('Fill uses a gradient, thus no foreground color is available');
|
||||
}
|
||||
|
||||
return $this->foregroundColor;
|
||||
}
|
||||
|
||||
public function getForegroundGradient() : Gradient
|
||||
{
|
||||
if (null === $this->foregroundGradient) {
|
||||
throw new RuntimeException('Fill uses a single color, thus no foreground gradient is available');
|
||||
}
|
||||
|
||||
return $this->foregroundGradient;
|
||||
}
|
||||
|
||||
public function getTopLeftEyeFill() : EyeFill
|
||||
{
|
||||
return $this->topLeftEyeFill;
|
||||
}
|
||||
|
||||
public function getTopRightEyeFill() : EyeFill
|
||||
{
|
||||
return $this->topRightEyeFill;
|
||||
}
|
||||
|
||||
public function getBottomLeftEyeFill() : EyeFill
|
||||
{
|
||||
return $this->bottomLeftEyeFill;
|
||||
}
|
||||
}
|
46
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php
vendored
Normal file
46
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/Gradient.php
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\RendererStyle;
|
||||
|
||||
use BaconQrCode\Renderer\Color\ColorInterface;
|
||||
|
||||
final class Gradient
|
||||
{
|
||||
/**
|
||||
* @var ColorInterface
|
||||
*/
|
||||
private $startColor;
|
||||
|
||||
/**
|
||||
* @var ColorInterface
|
||||
*/
|
||||
private $endColor;
|
||||
|
||||
/**
|
||||
* @var GradientType
|
||||
*/
|
||||
private $type;
|
||||
|
||||
public function __construct(ColorInterface $startColor, ColorInterface $endColor, GradientType $type)
|
||||
{
|
||||
$this->startColor = $startColor;
|
||||
$this->endColor = $endColor;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function getStartColor() : ColorInterface
|
||||
{
|
||||
return $this->startColor;
|
||||
}
|
||||
|
||||
public function getEndColor() : ColorInterface
|
||||
{
|
||||
return $this->endColor;
|
||||
}
|
||||
|
||||
public function getType() : GradientType
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
}
|
22
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php
vendored
Normal file
22
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/GradientType.php
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\RendererStyle;
|
||||
|
||||
use DASPRiD\Enum\AbstractEnum;
|
||||
|
||||
/**
|
||||
* @method static self VERTICAL()
|
||||
* @method static self HORIZONTAL()
|
||||
* @method static self DIAGONAL()
|
||||
* @method static self INVERSE_DIAGONAL()
|
||||
* @method static self RADIAL()
|
||||
*/
|
||||
final class GradientType extends AbstractEnum
|
||||
{
|
||||
protected const VERTICAL = null;
|
||||
protected const HORIZONTAL = null;
|
||||
protected const DIAGONAL = null;
|
||||
protected const INVERSE_DIAGONAL = null;
|
||||
protected const RADIAL = null;
|
||||
}
|
90
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/RendererStyle.php
vendored
Normal file
90
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Renderer/RendererStyle/RendererStyle.php
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode\Renderer\RendererStyle;
|
||||
|
||||
use BaconQrCode\Renderer\Eye\EyeInterface;
|
||||
use BaconQrCode\Renderer\Eye\ModuleEye;
|
||||
use BaconQrCode\Renderer\Module\ModuleInterface;
|
||||
use BaconQrCode\Renderer\Module\SquareModule;
|
||||
|
||||
final class RendererStyle
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $size;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $margin;
|
||||
|
||||
/**
|
||||
* @var ModuleInterface
|
||||
*/
|
||||
private $module;
|
||||
|
||||
/**
|
||||
* @var EyeInterface|null
|
||||
*/
|
||||
private $eye;
|
||||
|
||||
/**
|
||||
* @var Fill
|
||||
*/
|
||||
private $fill;
|
||||
|
||||
public function __construct(
|
||||
int $size,
|
||||
int $margin = 4,
|
||||
?ModuleInterface $module = null,
|
||||
?EyeInterface $eye = null,
|
||||
?Fill $fill = null
|
||||
) {
|
||||
$this->margin = $margin;
|
||||
$this->size = $size;
|
||||
$this->module = $module ?: SquareModule::instance();
|
||||
$this->eye = $eye ?: new ModuleEye($this->module);
|
||||
$this->fill = $fill ?: Fill::default();
|
||||
}
|
||||
|
||||
public function withSize(int $size) : self
|
||||
{
|
||||
$style = clone $this;
|
||||
$style->size = $size;
|
||||
return $style;
|
||||
}
|
||||
|
||||
public function withMargin(int $margin) : self
|
||||
{
|
||||
$style = clone $this;
|
||||
$style->margin = $margin;
|
||||
return $style;
|
||||
}
|
||||
|
||||
public function getSize() : int
|
||||
{
|
||||
return $this->size;
|
||||
}
|
||||
|
||||
public function getMargin() : int
|
||||
{
|
||||
return $this->margin;
|
||||
}
|
||||
|
||||
public function getModule() : ModuleInterface
|
||||
{
|
||||
return $this->module;
|
||||
}
|
||||
|
||||
public function getEye() : EyeInterface
|
||||
{
|
||||
return $this->eye;
|
||||
}
|
||||
|
||||
public function getFill() : Fill
|
||||
{
|
||||
return $this->fill;
|
||||
}
|
||||
}
|
71
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Writer.php
vendored
Normal file
71
admin/phpMyAdmin/vendor/bacon/bacon-qr-code/src/Writer.php
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
<?php
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace BaconQrCode;
|
||||
|
||||
use BaconQrCode\Common\ErrorCorrectionLevel;
|
||||
use BaconQrCode\Common\Version;
|
||||
use BaconQrCode\Encoder\Encoder;
|
||||
use BaconQrCode\Exception\InvalidArgumentException;
|
||||
use BaconQrCode\Renderer\RendererInterface;
|
||||
|
||||
/**
|
||||
* QR code writer.
|
||||
*/
|
||||
final class Writer
|
||||
{
|
||||
/**
|
||||
* Renderer instance.
|
||||
*
|
||||
* @var RendererInterface
|
||||
*/
|
||||
private $renderer;
|
||||
|
||||
/**
|
||||
* Creates a new writer with a specific renderer.
|
||||
*/
|
||||
public function __construct(RendererInterface $renderer)
|
||||
{
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes QR code and returns it as string.
|
||||
*
|
||||
* Content is a string which *should* be encoded in UTF-8, in case there are
|
||||
* non ASCII-characters present.
|
||||
*
|
||||
* @throws InvalidArgumentException if the content is empty
|
||||
*/
|
||||
public function writeString(
|
||||
string $content,
|
||||
string $encoding = Encoder::DEFAULT_BYTE_MODE_ECODING,
|
||||
?ErrorCorrectionLevel $ecLevel = null,
|
||||
?Version $forcedVersion = null
|
||||
) : string {
|
||||
if (strlen($content) === 0) {
|
||||
throw new InvalidArgumentException('Found empty contents');
|
||||
}
|
||||
|
||||
if (null === $ecLevel) {
|
||||
$ecLevel = ErrorCorrectionLevel::L();
|
||||
}
|
||||
|
||||
return $this->renderer->render(Encoder::encode($content, $ecLevel, $encoding, $forcedVersion));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes QR code to a file.
|
||||
*
|
||||
* @see Writer::writeString()
|
||||
*/
|
||||
public function writeFile(
|
||||
string $content,
|
||||
string $filename,
|
||||
string $encoding = Encoder::DEFAULT_BYTE_MODE_ECODING,
|
||||
?ErrorCorrectionLevel $ecLevel = null,
|
||||
?Version $forcedVersion = null
|
||||
) : void {
|
||||
file_put_contents($filename, $this->writeString($content, $encoding, $ecLevel, $forcedVersion));
|
||||
}
|
||||
}
|
11
admin/phpMyAdmin/vendor/beberlei/assert/LICENSE
vendored
Normal file
11
admin/phpMyAdmin/vendor/beberlei/assert/LICENSE
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
Copyright (c) 2011-2013, Benjamin Eberlei
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
64
admin/phpMyAdmin/vendor/beberlei/assert/composer.json
vendored
Normal file
64
admin/phpMyAdmin/vendor/beberlei/assert/composer.json
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"name": "beberlei/assert",
|
||||
"description": "Thin assertion library for input validation in business models.",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Benjamin Eberlei",
|
||||
"email": "kontakt@beberlei.de",
|
||||
"role": "Lead Developer"
|
||||
},
|
||||
{
|
||||
"name": "Richard Quadling",
|
||||
"email": "rquadling@gmail.com",
|
||||
"role": "Collaborator"
|
||||
}
|
||||
],
|
||||
"license": "BSD-2-Clause",
|
||||
"keywords": [
|
||||
"assert",
|
||||
"assertion",
|
||||
"validation"
|
||||
],
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.0 || ^8.0",
|
||||
"ext-simplexml": "*",
|
||||
"ext-mbstring": "*",
|
||||
"ext-ctype": "*",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"friendsofphp/php-cs-fixer": "*",
|
||||
"phpstan/phpstan": "*",
|
||||
"phpunit/phpunit": ">=6.0.0",
|
||||
"yoast/phpunit-polyfills": "^0.1.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Assert\\": "lib/Assert"
|
||||
},
|
||||
"files": [
|
||||
"lib/Assert/functions.php"
|
||||
]
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Assert\\Tests\\": "tests/Assert/Tests"
|
||||
},
|
||||
"files": [
|
||||
"tests/Assert/Tests/Fixtures/functions.php"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"assert:generate-docs": "php bin/generate_method_docs.php",
|
||||
"assert:cs-lint": "php-cs-fixer fix --diff -vvv --dry-run",
|
||||
"assert:cs-fix": "php-cs-fixer fix . -vvv || true",
|
||||
"assert:sa-code": "vendor/bin/phpstan analyse --configuration=phpstan-code.neon --no-progress --ansi -l 7 bin lib",
|
||||
"assert:sa-tests": "vendor/bin/phpstan analyse --configuration=phpstan-tests.neon --no-progress --ansi -l 7 tests"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-intl": "Needed to allow Assertion::count(), Assertion::isCountable(), Assertion::minCount(), and Assertion::maxCount() to operate on ResourceBundles"
|
||||
}
|
||||
}
|
85
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/Assert.php
vendored
Normal file
85
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/Assert.php
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Assert
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to kontakt@beberlei.de so I can send you a copy immediately.
|
||||
*/
|
||||
|
||||
namespace Assert;
|
||||
|
||||
/**
|
||||
* AssertionChain factory.
|
||||
*/
|
||||
abstract class Assert
|
||||
{
|
||||
/** @var string */
|
||||
protected static $lazyAssertionExceptionClass = LazyAssertionException::class;
|
||||
|
||||
/** @var string */
|
||||
protected static $assertionClass = Assertion::class;
|
||||
|
||||
/**
|
||||
* Start validation on a value, returns {@link AssertionChain}.
|
||||
*
|
||||
* The invocation of this method starts an assertion chain
|
||||
* that is happening on the passed value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string|callable|null $defaultMessage
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* Assert::that($value)->notEmpty()->integer();
|
||||
* Assert::that($value)->nullOr()->string()->startsWith("Foo");
|
||||
*
|
||||
* The assertion chain can be stateful, that means be careful when you reuse
|
||||
* it. You should never pass around the chain.
|
||||
*/
|
||||
public static function that($value, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain
|
||||
{
|
||||
$assertionChain = new AssertionChain($value, $defaultMessage, $defaultPropertyPath);
|
||||
|
||||
return $assertionChain->setAssertionClassName(static::$assertionClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start validation on a set of values, returns {@link AssertionChain}.
|
||||
*
|
||||
* @param mixed $values
|
||||
* @param string|callable|null $defaultMessage
|
||||
*/
|
||||
public static function thatAll($values, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain
|
||||
{
|
||||
return static::that($values, $defaultMessage, $defaultPropertyPath)->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start validation and allow NULL, returns {@link AssertionChain}.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string|callable|null $defaultMessage
|
||||
*/
|
||||
public static function thatNullOr($value, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain
|
||||
{
|
||||
return static::that($value, $defaultMessage, $defaultPropertyPath)->nullOr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a lazy assertion object.
|
||||
*/
|
||||
public static function lazy(): LazyAssertion
|
||||
{
|
||||
$lazyAssertion = new LazyAssertion();
|
||||
|
||||
return $lazyAssertion
|
||||
->setAssertClass(\get_called_class())
|
||||
->setExceptionClass(static::$lazyAssertionExceptionClass);
|
||||
}
|
||||
}
|
2797
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/Assertion.php
vendored
Normal file
2797
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/Assertion.php
vendored
Normal file
File diff suppressed because it is too large
Load diff
247
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/AssertionChain.php
vendored
Normal file
247
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/AssertionChain.php
vendored
Normal file
|
@ -0,0 +1,247 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Assert
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to kontakt@beberlei.de so I can send you a copy immediately.
|
||||
*/
|
||||
|
||||
namespace Assert;
|
||||
|
||||
use LogicException;
|
||||
|
||||
/**
|
||||
* Chaining builder for assertions.
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*
|
||||
* @method AssertionChain alnum(string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric.
|
||||
* @method AssertionChain base64(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined.
|
||||
* @method AssertionChain between(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit.
|
||||
* @method AssertionChain betweenExclusive(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit.
|
||||
* @method AssertionChain betweenLength(int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths.
|
||||
* @method AssertionChain boolean(string|callable $message = null, string $propertyPath = null) Assert that value is php boolean.
|
||||
* @method AssertionChain choice(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices.
|
||||
* @method AssertionChain choicesNotEmpty(array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content.
|
||||
* @method AssertionChain classExists(string|callable $message = null, string $propertyPath = null) Assert that the class exists.
|
||||
* @method AssertionChain contains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars.
|
||||
* @method AssertionChain count(int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count.
|
||||
* @method AssertionChain date(string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format.
|
||||
* @method AssertionChain defined(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined.
|
||||
* @method AssertionChain digit(string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit.
|
||||
* @method AssertionChain directory(string|callable $message = null, string $propertyPath = null) Assert that a directory exists.
|
||||
* @method AssertionChain e164(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number.
|
||||
* @method AssertionChain email(string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL).
|
||||
* @method AssertionChain endsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars.
|
||||
* @method AssertionChain eq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==).
|
||||
* @method AssertionChain eqArraySubset(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset.
|
||||
* @method AssertionChain extensionLoaded(string|callable $message = null, string $propertyPath = null) Assert that extension is loaded.
|
||||
* @method AssertionChain extensionVersion(string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed.
|
||||
* @method AssertionChain false(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False.
|
||||
* @method AssertionChain file(string|callable $message = null, string $propertyPath = null) Assert that a file exists.
|
||||
* @method AssertionChain float(string|callable $message = null, string $propertyPath = null) Assert that value is a php float.
|
||||
* @method AssertionChain greaterOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit.
|
||||
* @method AssertionChain greaterThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit.
|
||||
* @method AssertionChain implementsInterface(string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface.
|
||||
* @method AssertionChain inArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice().
|
||||
* @method AssertionChain integer(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer.
|
||||
* @method AssertionChain integerish(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish.
|
||||
* @method AssertionChain interfaceExists(string|callable $message = null, string $propertyPath = null) Assert that the interface exists.
|
||||
* @method AssertionChain ip(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address.
|
||||
* @method AssertionChain ipv4(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address.
|
||||
* @method AssertionChain ipv6(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address.
|
||||
* @method AssertionChain isArray(string|callable $message = null, string $propertyPath = null) Assert that value is an array.
|
||||
* @method AssertionChain isArrayAccessible(string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object.
|
||||
* @method AssertionChain isCallable(string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable.
|
||||
* @method AssertionChain isCountable(string|callable $message = null, string $propertyPath = null) Assert that value is countable.
|
||||
* @method AssertionChain isInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name.
|
||||
* @method AssertionChain isJsonString(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string.
|
||||
* @method AssertionChain isObject(string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object.
|
||||
* @method AssertionChain isResource(string|callable $message = null, string $propertyPath = null) Assert that value is a resource.
|
||||
* @method AssertionChain isTraversable(string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object.
|
||||
* @method AssertionChain keyExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array.
|
||||
* @method AssertionChain keyIsset(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset().
|
||||
* @method AssertionChain keyNotExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array.
|
||||
* @method AssertionChain length(int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length.
|
||||
* @method AssertionChain lessOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit.
|
||||
* @method AssertionChain lessThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit.
|
||||
* @method AssertionChain max(mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit.
|
||||
* @method AssertionChain maxCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements.
|
||||
* @method AssertionChain maxLength(int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars.
|
||||
* @method AssertionChain methodExists(mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object.
|
||||
* @method AssertionChain min(mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit.
|
||||
* @method AssertionChain minCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements.
|
||||
* @method AssertionChain minLength(int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long.
|
||||
* @method AssertionChain noContent(string|callable $message = null, string $propertyPath = null) Assert that value is empty.
|
||||
* @method AssertionChain notBlank(string|callable $message = null, string $propertyPath = null) Assert that value is not blank.
|
||||
* @method AssertionChain notContains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars.
|
||||
* @method AssertionChain notEmpty(string|callable $message = null, string $propertyPath = null) Assert that value is not empty.
|
||||
* @method AssertionChain notEmptyKey(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty.
|
||||
* @method AssertionChain notEq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==).
|
||||
* @method AssertionChain notInArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices.
|
||||
* @method AssertionChain notIsInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name.
|
||||
* @method AssertionChain notNull(string|callable $message = null, string $propertyPath = null) Assert that value is not null.
|
||||
* @method AssertionChain notRegex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex.
|
||||
* @method AssertionChain notSame(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===).
|
||||
* @method AssertionChain null(string|callable $message = null, string $propertyPath = null) Assert that value is null.
|
||||
* @method AssertionChain numeric(string|callable $message = null, string $propertyPath = null) Assert that value is numeric.
|
||||
* @method AssertionChain objectOrClass(string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists.
|
||||
* @method AssertionChain phpVersion(mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version.
|
||||
* @method AssertionChain propertiesExist(array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist.
|
||||
* @method AssertionChain propertyExists(string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists.
|
||||
* @method AssertionChain range(mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers.
|
||||
* @method AssertionChain readable(string|callable $message = null, string $propertyPath = null) Assert that the value is something readable.
|
||||
* @method AssertionChain regex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex.
|
||||
* @method AssertionChain same(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===).
|
||||
* @method AssertionChain satisfy(callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback.
|
||||
* @method AssertionChain scalar(string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar.
|
||||
* @method AssertionChain startsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars.
|
||||
* @method AssertionChain string(string|callable $message = null, string $propertyPath = null) Assert that value is a string.
|
||||
* @method AssertionChain subclassOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name.
|
||||
* @method AssertionChain true(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True.
|
||||
* @method AssertionChain uniqueValues(string|callable $message = null, string $propertyPath = null) Assert that values in array are unique (using strict equality).
|
||||
* @method AssertionChain url(string|callable $message = null, string $propertyPath = null) Assert that value is an URL.
|
||||
* @method AssertionChain uuid(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID.
|
||||
* @method AssertionChain version(string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions.
|
||||
* @method AssertionChain writeable(string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable.
|
||||
*/
|
||||
class AssertionChain
|
||||
{
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @var string|callable|null
|
||||
*/
|
||||
private $defaultMessage;
|
||||
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $defaultPropertyPath;
|
||||
|
||||
/**
|
||||
* Return each assertion as always valid.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $alwaysValid = false;
|
||||
|
||||
/**
|
||||
* Perform assertion on every element of array or traversable.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $all = false;
|
||||
|
||||
/** @var string|Assertion Class to use for assertion calls */
|
||||
private $assertionClassName = 'Assert\Assertion';
|
||||
|
||||
/**
|
||||
* AssertionChain constructor.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string|callable|null $defaultMessage
|
||||
*/
|
||||
public function __construct($value, $defaultMessage = null, string $defaultPropertyPath = null)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->defaultMessage = $defaultMessage;
|
||||
$this->defaultPropertyPath = $defaultPropertyPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call assertion on the current value in the chain.
|
||||
*
|
||||
* @param string $methodName
|
||||
* @param array $args
|
||||
*/
|
||||
public function __call($methodName, $args): AssertionChain
|
||||
{
|
||||
if (true === $this->alwaysValid) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
try {
|
||||
$method = new \ReflectionMethod($this->assertionClassName, $methodName);
|
||||
} catch (\ReflectionException $exception) {
|
||||
throw new \RuntimeException("Assertion '".$methodName."' does not exist.");
|
||||
}
|
||||
|
||||
\array_unshift($args, $this->value);
|
||||
$params = $method->getParameters();
|
||||
|
||||
foreach ($params as $idx => $param) {
|
||||
if (isset($args[$idx])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($param->getName()) {
|
||||
case 'message':
|
||||
$args[$idx] = $this->defaultMessage;
|
||||
break;
|
||||
case 'propertyPath':
|
||||
$args[$idx] = $this->defaultPropertyPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->all) {
|
||||
$methodName = 'all'.$methodName;
|
||||
}
|
||||
|
||||
\call_user_func_array([$this->assertionClassName, $methodName], $args);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch chain into validation mode for an array of values.
|
||||
*/
|
||||
public function all(): AssertionChain
|
||||
{
|
||||
$this->all = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch chain into mode allowing nulls, ignoring further assertions.
|
||||
*/
|
||||
public function nullOr(): AssertionChain
|
||||
{
|
||||
if (null === $this->value) {
|
||||
$this->alwaysValid = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function setAssertionClassName($className): AssertionChain
|
||||
{
|
||||
if (!\is_string($className)) {
|
||||
throw new LogicException('Exception class name must be passed as a string');
|
||||
}
|
||||
|
||||
if (Assertion::class !== $className && !\is_subclass_of($className, Assertion::class)) {
|
||||
throw new LogicException($className.' is not (a subclass of) '.Assertion::class);
|
||||
}
|
||||
|
||||
$this->assertionClassName = $className;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
32
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/AssertionFailedException.php
vendored
Normal file
32
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/AssertionFailedException.php
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Assert
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to kontakt@beberlei.de so I can send you a copy immediately.
|
||||
*/
|
||||
|
||||
namespace Assert;
|
||||
|
||||
use Throwable;
|
||||
|
||||
interface AssertionFailedException extends Throwable
|
||||
{
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPropertyPath();
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getValue();
|
||||
|
||||
public function getConstraints(): array;
|
||||
}
|
74
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/InvalidArgumentException.php
vendored
Normal file
74
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/InvalidArgumentException.php
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Assert
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to kontakt@beberlei.de so I can send you a copy immediately.
|
||||
*/
|
||||
|
||||
namespace Assert;
|
||||
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements AssertionFailedException
|
||||
{
|
||||
/**
|
||||
* @var string|null
|
||||
*/
|
||||
private $propertyPath;
|
||||
|
||||
/**
|
||||
* @var mixed
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $constraints;
|
||||
|
||||
public function __construct($message, $code, string $propertyPath = null, $value = null, array $constraints = [])
|
||||
{
|
||||
parent::__construct($message, $code);
|
||||
|
||||
$this->propertyPath = $propertyPath;
|
||||
$this->value = $value;
|
||||
$this->constraints = $constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* User controlled way to define a sub-property causing
|
||||
* the failure of a currently asserted objects.
|
||||
*
|
||||
* Useful to transport information about the nature of the error
|
||||
* back to higher layers.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function getPropertyPath()
|
||||
{
|
||||
return $this->propertyPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value that caused the assertion to fail.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the constraints that applied to the failed assertion.
|
||||
*/
|
||||
public function getConstraints(): array
|
||||
{
|
||||
return $this->constraints;
|
||||
}
|
||||
}
|
228
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/LazyAssertion.php
vendored
Normal file
228
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/LazyAssertion.php
vendored
Normal file
|
@ -0,0 +1,228 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Assert
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to kontakt@beberlei.de so I can send you a copy immediately.
|
||||
*/
|
||||
|
||||
namespace Assert;
|
||||
|
||||
use LogicException;
|
||||
|
||||
/**
|
||||
* Chaining builder for lazy assertions.
|
||||
*
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*
|
||||
* @method LazyAssertion alnum(string|callable $message = null, string $propertyPath = null) Assert that value is alphanumeric.
|
||||
* @method LazyAssertion base64(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined.
|
||||
* @method LazyAssertion between(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater or equal than a lower limit, and less than or equal to an upper limit.
|
||||
* @method LazyAssertion betweenExclusive(mixed $lowerLimit, mixed $upperLimit, string|callable $message = null, string $propertyPath = null) Assert that a value is greater than a lower limit, and less than an upper limit.
|
||||
* @method LazyAssertion betweenLength(int $minLength, int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string length is between min and max lengths.
|
||||
* @method LazyAssertion boolean(string|callable $message = null, string $propertyPath = null) Assert that value is php boolean.
|
||||
* @method LazyAssertion choice(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices.
|
||||
* @method LazyAssertion choicesNotEmpty(array $choices, string|callable $message = null, string $propertyPath = null) Determines if the values array has every choice as key and that this choice has content.
|
||||
* @method LazyAssertion classExists(string|callable $message = null, string $propertyPath = null) Assert that the class exists.
|
||||
* @method LazyAssertion contains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string contains a sequence of chars.
|
||||
* @method LazyAssertion count(int $count, string|callable $message = null, string $propertyPath = null) Assert that the count of countable is equal to count.
|
||||
* @method LazyAssertion date(string $format, string|callable $message = null, string $propertyPath = null) Assert that date is valid and corresponds to the given format.
|
||||
* @method LazyAssertion defined(string|callable $message = null, string $propertyPath = null) Assert that a constant is defined.
|
||||
* @method LazyAssertion digit(string|callable $message = null, string $propertyPath = null) Validates if an integer or integerish is a digit.
|
||||
* @method LazyAssertion directory(string|callable $message = null, string $propertyPath = null) Assert that a directory exists.
|
||||
* @method LazyAssertion e164(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid E164 Phone Number.
|
||||
* @method LazyAssertion email(string|callable $message = null, string $propertyPath = null) Assert that value is an email address (using input_filter/FILTER_VALIDATE_EMAIL).
|
||||
* @method LazyAssertion endsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string ends with a sequence of chars.
|
||||
* @method LazyAssertion eq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are equal (using ==).
|
||||
* @method LazyAssertion eqArraySubset(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that the array contains the subset.
|
||||
* @method LazyAssertion extensionLoaded(string|callable $message = null, string $propertyPath = null) Assert that extension is loaded.
|
||||
* @method LazyAssertion extensionVersion(string $operator, mixed $version, string|callable $message = null, string $propertyPath = null) Assert that extension is loaded and a specific version is installed.
|
||||
* @method LazyAssertion false(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean False.
|
||||
* @method LazyAssertion file(string|callable $message = null, string $propertyPath = null) Assert that a file exists.
|
||||
* @method LazyAssertion float(string|callable $message = null, string $propertyPath = null) Assert that value is a php float.
|
||||
* @method LazyAssertion greaterOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater or equal than given limit.
|
||||
* @method LazyAssertion greaterThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is greater than given limit.
|
||||
* @method LazyAssertion implementsInterface(string $interfaceName, string|callable $message = null, string $propertyPath = null) Assert that the class implements the interface.
|
||||
* @method LazyAssertion inArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is in array of choices. This is an alias of Assertion::choice().
|
||||
* @method LazyAssertion integer(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer.
|
||||
* @method LazyAssertion integerish(string|callable $message = null, string $propertyPath = null) Assert that value is a php integer'ish.
|
||||
* @method LazyAssertion interfaceExists(string|callable $message = null, string $propertyPath = null) Assert that the interface exists.
|
||||
* @method LazyAssertion ip(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 or IPv6 address.
|
||||
* @method LazyAssertion ipv4(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv4 address.
|
||||
* @method LazyAssertion ipv6(int $flag = null, string|callable $message = null, string $propertyPath = null) Assert that value is an IPv6 address.
|
||||
* @method LazyAssertion isArray(string|callable $message = null, string $propertyPath = null) Assert that value is an array.
|
||||
* @method LazyAssertion isArrayAccessible(string|callable $message = null, string $propertyPath = null) Assert that value is an array or an array-accessible object.
|
||||
* @method LazyAssertion isCallable(string|callable $message = null, string $propertyPath = null) Determines that the provided value is callable.
|
||||
* @method LazyAssertion isCountable(string|callable $message = null, string $propertyPath = null) Assert that value is countable.
|
||||
* @method LazyAssertion isInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is instance of given class-name.
|
||||
* @method LazyAssertion isJsonString(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid json string.
|
||||
* @method LazyAssertion isObject(string|callable $message = null, string $propertyPath = null) Determines that the provided value is an object.
|
||||
* @method LazyAssertion isResource(string|callable $message = null, string $propertyPath = null) Assert that value is a resource.
|
||||
* @method LazyAssertion isTraversable(string|callable $message = null, string $propertyPath = null) Assert that value is an array or a traversable object.
|
||||
* @method LazyAssertion keyExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array.
|
||||
* @method LazyAssertion keyIsset(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object using isset().
|
||||
* @method LazyAssertion keyNotExists(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key does not exist in an array.
|
||||
* @method LazyAssertion length(int $length, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string has a given length.
|
||||
* @method LazyAssertion lessOrEqualThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less or equal than given limit.
|
||||
* @method LazyAssertion lessThan(mixed $limit, string|callable $message = null, string $propertyPath = null) Determines if the value is less than given limit.
|
||||
* @method LazyAssertion max(mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that a number is smaller as a given limit.
|
||||
* @method LazyAssertion maxCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at most $count elements.
|
||||
* @method LazyAssertion maxLength(int $maxLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string value is not longer than $maxLength chars.
|
||||
* @method LazyAssertion methodExists(mixed $object, string|callable $message = null, string $propertyPath = null) Determines that the named method is defined in the provided object.
|
||||
* @method LazyAssertion min(mixed $minValue, string|callable $message = null, string $propertyPath = null) Assert that a value is at least as big as a given limit.
|
||||
* @method LazyAssertion minCount(int $count, string|callable $message = null, string $propertyPath = null) Assert that the countable have at least $count elements.
|
||||
* @method LazyAssertion minLength(int $minLength, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that a string is at least $minLength chars long.
|
||||
* @method LazyAssertion noContent(string|callable $message = null, string $propertyPath = null) Assert that value is empty.
|
||||
* @method LazyAssertion notBlank(string|callable $message = null, string $propertyPath = null) Assert that value is not blank.
|
||||
* @method LazyAssertion notContains(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string does not contains a sequence of chars.
|
||||
* @method LazyAssertion notEmpty(string|callable $message = null, string $propertyPath = null) Assert that value is not empty.
|
||||
* @method LazyAssertion notEmptyKey(string|int $key, string|callable $message = null, string $propertyPath = null) Assert that key exists in an array/array-accessible object and its value is not empty.
|
||||
* @method LazyAssertion notEq(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not equal (using ==).
|
||||
* @method LazyAssertion notInArray(array $choices, string|callable $message = null, string $propertyPath = null) Assert that value is not in array of choices.
|
||||
* @method LazyAssertion notIsInstanceOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is not instance of given class-name.
|
||||
* @method LazyAssertion notNull(string|callable $message = null, string $propertyPath = null) Assert that value is not null.
|
||||
* @method LazyAssertion notRegex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value does not match a regex.
|
||||
* @method LazyAssertion notSame(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are not the same (using ===).
|
||||
* @method LazyAssertion null(string|callable $message = null, string $propertyPath = null) Assert that value is null.
|
||||
* @method LazyAssertion numeric(string|callable $message = null, string $propertyPath = null) Assert that value is numeric.
|
||||
* @method LazyAssertion objectOrClass(string|callable $message = null, string $propertyPath = null) Assert that the value is an object, or a class that exists.
|
||||
* @method LazyAssertion phpVersion(mixed $version, string|callable $message = null, string $propertyPath = null) Assert on PHP version.
|
||||
* @method LazyAssertion propertiesExist(array $properties, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the properties all exist.
|
||||
* @method LazyAssertion propertyExists(string $property, string|callable $message = null, string $propertyPath = null) Assert that the value is an object or class, and that the property exists.
|
||||
* @method LazyAssertion range(mixed $minValue, mixed $maxValue, string|callable $message = null, string $propertyPath = null) Assert that value is in range of numbers.
|
||||
* @method LazyAssertion readable(string|callable $message = null, string $propertyPath = null) Assert that the value is something readable.
|
||||
* @method LazyAssertion regex(string $pattern, string|callable $message = null, string $propertyPath = null) Assert that value matches a regex.
|
||||
* @method LazyAssertion same(mixed $value2, string|callable $message = null, string $propertyPath = null) Assert that two values are the same (using ===).
|
||||
* @method LazyAssertion satisfy(callable $callback, string|callable $message = null, string $propertyPath = null) Assert that the provided value is valid according to a callback.
|
||||
* @method LazyAssertion scalar(string|callable $message = null, string $propertyPath = null) Assert that value is a PHP scalar.
|
||||
* @method LazyAssertion startsWith(string $needle, string|callable $message = null, string $propertyPath = null, string $encoding = 'utf8') Assert that string starts with a sequence of chars.
|
||||
* @method LazyAssertion string(string|callable $message = null, string $propertyPath = null) Assert that value is a string.
|
||||
* @method LazyAssertion subclassOf(string $className, string|callable $message = null, string $propertyPath = null) Assert that value is subclass of given class-name.
|
||||
* @method LazyAssertion true(string|callable $message = null, string $propertyPath = null) Assert that the value is boolean True.
|
||||
* @method LazyAssertion uniqueValues(string|callable $message = null, string $propertyPath = null) Assert that values in array are unique (using strict equality).
|
||||
* @method LazyAssertion url(string|callable $message = null, string $propertyPath = null) Assert that value is an URL.
|
||||
* @method LazyAssertion uuid(string|callable $message = null, string $propertyPath = null) Assert that the given string is a valid UUID.
|
||||
* @method LazyAssertion version(string $operator, string $version2, string|callable $message = null, string $propertyPath = null) Assert comparison of two versions.
|
||||
* @method LazyAssertion writeable(string|callable $message = null, string $propertyPath = null) Assert that the value is something writeable.
|
||||
* @method LazyAssertion all() Switch chain into validation mode for an array of values.
|
||||
* @method LazyAssertion nullOr() Switch chain into mode allowing nulls, ignoring further assertions.
|
||||
*/
|
||||
class LazyAssertion
|
||||
{
|
||||
private $currentChainFailed = false;
|
||||
private $alwaysTryAll = false;
|
||||
private $thisChainTryAll = false;
|
||||
private $currentChain;
|
||||
private $errors = [];
|
||||
|
||||
/** @var string The class to use as AssertionChain factory */
|
||||
private $assertClass = Assert::class;
|
||||
|
||||
/** @var string|LazyAssertionException The class to use for exceptions */
|
||||
private $exceptionClass = LazyAssertionException::class;
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param string|callable|null $defaultMessage
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function that($value, string $propertyPath = null, $defaultMessage = null)
|
||||
{
|
||||
$this->currentChainFailed = false;
|
||||
$this->thisChainTryAll = false;
|
||||
$assertClass = $this->assertClass;
|
||||
$this->currentChain = $assertClass::that($value, $defaultMessage, $propertyPath);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return static
|
||||
*/
|
||||
public function tryAll()
|
||||
{
|
||||
if (!$this->currentChain) {
|
||||
$this->alwaysTryAll = true;
|
||||
}
|
||||
|
||||
$this->thisChainTryAll = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function __call($method, $args)
|
||||
{
|
||||
if (false === $this->alwaysTryAll
|
||||
&& false === $this->thisChainTryAll
|
||||
&& true === $this->currentChainFailed
|
||||
) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
try {
|
||||
\call_user_func_array([$this->currentChain, $method], $args);
|
||||
} catch (AssertionFailedException $e) {
|
||||
$this->errors[] = $e;
|
||||
$this->currentChainFailed = true;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws LazyAssertionException
|
||||
*/
|
||||
public function verifyNow(): bool
|
||||
{
|
||||
if ($this->errors) {
|
||||
throw \call_user_func([$this->exceptionClass, 'fromErrors'], $this->errors);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setAssertClass(string $className): LazyAssertion
|
||||
{
|
||||
if (Assert::class !== $className && !\is_subclass_of($className, Assert::class)) {
|
||||
throw new LogicException($className.' is not (a subclass of) '.Assert::class);
|
||||
}
|
||||
|
||||
$this->assertClass = $className;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function setExceptionClass(string $className): LazyAssertion
|
||||
{
|
||||
if (LazyAssertionException::class !== $className && !\is_subclass_of($className, LazyAssertionException::class)) {
|
||||
throw new LogicException($className.' is not (a subclass of) '.LazyAssertionException::class);
|
||||
}
|
||||
|
||||
$this->exceptionClass = $className;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
53
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/LazyAssertionException.php
vendored
Normal file
53
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/LazyAssertionException.php
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Assert
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to kontakt@beberlei.de so I can send you a copy immediately.
|
||||
*/
|
||||
|
||||
namespace Assert;
|
||||
|
||||
class LazyAssertionException extends InvalidArgumentException
|
||||
{
|
||||
/**
|
||||
* @var InvalidArgumentException[]
|
||||
*/
|
||||
private $errors = [];
|
||||
|
||||
/**
|
||||
* @param InvalidArgumentException[] $errors
|
||||
*/
|
||||
public static function fromErrors(array $errors): self
|
||||
{
|
||||
$message = \sprintf('The following %d assertions failed:', \count($errors))."\n";
|
||||
|
||||
$i = 1;
|
||||
foreach ($errors as $error) {
|
||||
$message .= \sprintf("%d) %s: %s\n", $i++, $error->getPropertyPath(), $error->getMessage());
|
||||
}
|
||||
|
||||
return new static($message, $errors);
|
||||
}
|
||||
|
||||
public function __construct($message, array $errors)
|
||||
{
|
||||
parent::__construct($message, 0, null, null);
|
||||
|
||||
$this->errors = $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return InvalidArgumentException[]
|
||||
*/
|
||||
public function getErrorExceptions(): array
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
}
|
72
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/functions.php
vendored
Normal file
72
admin/phpMyAdmin/vendor/beberlei/assert/lib/Assert/functions.php
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Assert
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to kontakt@beberlei.de so I can send you a copy immediately.
|
||||
*/
|
||||
|
||||
namespace Assert;
|
||||
|
||||
/**
|
||||
* Start validation on a value, returns {@link AssertionChain}.
|
||||
*
|
||||
* The invocation of this method starts an assertion chain
|
||||
* that is happening on the passed value.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string|callable|null $defaultMessage
|
||||
* @param string $defaultPropertyPath
|
||||
*
|
||||
* @example
|
||||
*
|
||||
* \Assert\that($value)->notEmpty()->integer();
|
||||
* \Assert\that($value)->nullOr()->string()->startsWith("Foo");
|
||||
*
|
||||
* The assertion chain can be stateful, that means be careful when you reuse
|
||||
* it. You should never pass around the chain.
|
||||
*/
|
||||
function that($value, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain
|
||||
{
|
||||
return Assert::that($value, $defaultMessage, $defaultPropertyPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start validation on a set of values, returns {@link AssertionChain}.
|
||||
*
|
||||
* @param mixed $values
|
||||
* @param string|callable|null $defaultMessage
|
||||
* @param string $defaultPropertyPath
|
||||
*/
|
||||
function thatAll($values, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain
|
||||
{
|
||||
return Assert::thatAll($values, $defaultMessage, $defaultPropertyPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start validation and allow NULL, returns {@link AssertionChain}.
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param string|callable|null $defaultMessage
|
||||
* @param string $defaultPropertyPath
|
||||
*
|
||||
* @deprecated In favour of Assert::thatNullOr($value, $defaultMessage = null, $defaultPropertyPath = null)
|
||||
*/
|
||||
function thatNullOr($value, $defaultMessage = null, string $defaultPropertyPath = null): AssertionChain
|
||||
{
|
||||
return Assert::thatNullOr($value, $defaultMessage, $defaultPropertyPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a lazy assertion object.
|
||||
*/
|
||||
function lazy(): LazyAssertion
|
||||
{
|
||||
return Assert::lazy();
|
||||
}
|
20
admin/phpMyAdmin/vendor/brick/math/LICENSE
vendored
Normal file
20
admin/phpMyAdmin/vendor/brick/math/LICENSE
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-present Benjamin Morel
|
||||
|
||||
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.
|
35
admin/phpMyAdmin/vendor/brick/math/composer.json
vendored
Normal file
35
admin/phpMyAdmin/vendor/brick/math/composer.json
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "brick/math",
|
||||
"description": "Arbitrary-precision arithmetic library",
|
||||
"type": "library",
|
||||
"keywords": [
|
||||
"Brick",
|
||||
"Math",
|
||||
"Arbitrary-precision",
|
||||
"Arithmetic",
|
||||
"BigInteger",
|
||||
"BigDecimal",
|
||||
"BigRational",
|
||||
"Bignum"
|
||||
],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^7.1|^8.0",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.5.15|^8.5",
|
||||
"php-coveralls/php-coveralls": "^2.2",
|
||||
"vimeo/psalm": "^3.5"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Brick\\Math\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Brick\\Math\\Tests\\": "tests/"
|
||||
}
|
||||
}
|
||||
}
|
855
admin/phpMyAdmin/vendor/brick/math/src/BigDecimal.php
vendored
Normal file
855
admin/phpMyAdmin/vendor/brick/math/src/BigDecimal.php
vendored
Normal file
|
@ -0,0 +1,855 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math;
|
||||
|
||||
use Brick\Math\Exception\DivisionByZeroException;
|
||||
use Brick\Math\Exception\MathException;
|
||||
use Brick\Math\Exception\NegativeNumberException;
|
||||
use Brick\Math\Internal\Calculator;
|
||||
|
||||
/**
|
||||
* Immutable, arbitrary-precision signed decimal numbers.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
final class BigDecimal extends BigNumber
|
||||
{
|
||||
/**
|
||||
* The unscaled value of this decimal number.
|
||||
*
|
||||
* This is a string of digits with an optional leading minus sign.
|
||||
* No leading zero must be present.
|
||||
* No leading minus sign must be present if the value is 0.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* The scale (number of digits after the decimal point) of this decimal number.
|
||||
*
|
||||
* This must be zero or more.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $scale;
|
||||
|
||||
/**
|
||||
* Protected constructor. Use a factory method to obtain an instance.
|
||||
*
|
||||
* @param string $value The unscaled value, validated.
|
||||
* @param int $scale The scale, validated.
|
||||
*/
|
||||
protected function __construct(string $value, int $scale = 0)
|
||||
{
|
||||
$this->value = $value;
|
||||
$this->scale = $scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigDecimal of the given value.
|
||||
*
|
||||
* @param BigNumber|int|float|string $value
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigDecimal.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of($value) : BigNumber
|
||||
{
|
||||
return parent::of($value)->toBigDecimal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigDecimal from an unscaled value and a scale.
|
||||
*
|
||||
* Example: `(12345, 3)` will result in the BigDecimal `12.345`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $value The unscaled value. Must be convertible to a BigInteger.
|
||||
* @param int $scale The scale of the number, positive or zero.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @throws \InvalidArgumentException If the scale is negative.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ofUnscaledValue($value, int $scale = 0) : BigDecimal
|
||||
{
|
||||
if ($scale < 0) {
|
||||
throw new \InvalidArgumentException('The scale cannot be negative.');
|
||||
}
|
||||
|
||||
return new BigDecimal((string) BigInteger::of($value), $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigDecimal representing zero, with a scale of zero.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function zero() : BigDecimal
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $zero;
|
||||
|
||||
if ($zero === null) {
|
||||
$zero = new BigDecimal('0');
|
||||
}
|
||||
|
||||
return $zero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigDecimal representing one, with a scale of zero.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function one() : BigDecimal
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $one;
|
||||
|
||||
if ($one === null) {
|
||||
$one = new BigDecimal('1');
|
||||
}
|
||||
|
||||
return $one;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigDecimal representing ten, with a scale of zero.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ten() : BigDecimal
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $ten;
|
||||
|
||||
if ($ten === null) {
|
||||
$ten = new BigDecimal('10');
|
||||
}
|
||||
|
||||
return $ten;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of this number and the given one.
|
||||
*
|
||||
* The result has a scale of `max($this->scale, $that->scale)`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The number to add. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @return BigDecimal The result.
|
||||
*
|
||||
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function plus($that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->value === '0' && $that->scale <= $this->scale) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($this->value === '0' && $this->scale <= $that->scale) {
|
||||
return $that;
|
||||
}
|
||||
|
||||
[$a, $b] = $this->scaleValues($this, $that);
|
||||
|
||||
$value = Calculator::get()->add($a, $b);
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference of this number and the given one.
|
||||
*
|
||||
* The result has a scale of `max($this->scale, $that->scale)`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The number to subtract. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @return BigDecimal The result.
|
||||
*
|
||||
* @throws MathException If the number is not valid, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function minus($that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->value === '0' && $that->scale <= $this->scale) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
[$a, $b] = $this->scaleValues($this, $that);
|
||||
|
||||
$value = Calculator::get()->sub($a, $b);
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the product of this number and the given one.
|
||||
*
|
||||
* The result has a scale of `$this->scale + $that->scale`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The multiplier. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @return BigDecimal The result.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number, or is not convertible to a BigDecimal.
|
||||
*/
|
||||
public function multipliedBy($that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->value === '1' && $that->scale === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($this->value === '1' && $this->scale === 0) {
|
||||
return $that;
|
||||
}
|
||||
|
||||
$value = Calculator::get()->mul($this->value, $that->value);
|
||||
$scale = $this->scale + $that->scale;
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of the division of this number by the given one, at the given scale.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor.
|
||||
* @param int|null $scale The desired scale, or null to use the scale of this number.
|
||||
* @param int $roundingMode An optional rounding mode.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @throws \InvalidArgumentException If the scale or rounding mode is invalid.
|
||||
* @throws MathException If the number is invalid, is zero, or rounding was necessary.
|
||||
*/
|
||||
public function dividedBy($that, ?int $scale = null, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->isZero()) {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
if ($scale === null) {
|
||||
$scale = $this->scale;
|
||||
} elseif ($scale < 0) {
|
||||
throw new \InvalidArgumentException('Scale cannot be negative.');
|
||||
}
|
||||
|
||||
if ($that->value === '1' && $that->scale === 0 && $scale === $this->scale) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$p = $this->valueWithMinScale($that->scale + $scale);
|
||||
$q = $that->valueWithMinScale($this->scale - $scale);
|
||||
|
||||
$result = Calculator::get()->divRound($p, $q, $roundingMode);
|
||||
|
||||
return new BigDecimal($result, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exact result of the division of this number by the given one.
|
||||
*
|
||||
* The scale of the result is automatically calculated to fit all the fraction digits.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @return BigDecimal The result.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, is not convertible to a BigDecimal, is zero,
|
||||
* or the result yields an infinite number of digits.
|
||||
*/
|
||||
public function exactlyDividedBy($that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->value === '0') {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
[$a, $b] = $this->scaleValues($this, $that);
|
||||
|
||||
$d = \rtrim($b, '0');
|
||||
$scale = \strlen($b) - \strlen($d);
|
||||
|
||||
$calculator = Calculator::get();
|
||||
|
||||
foreach ([5, 2] as $prime) {
|
||||
for (;;) {
|
||||
$lastDigit = (int) $d[-1];
|
||||
|
||||
if ($lastDigit % $prime !== 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
$d = $calculator->divQ($d, (string) $prime);
|
||||
$scale++;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->dividedBy($that, $scale)->stripTrailingZeros();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this number exponentiated to the given value.
|
||||
*
|
||||
* The result has a scale of `$this->scale * $exponent`.
|
||||
*
|
||||
* @param int $exponent The exponent.
|
||||
*
|
||||
* @return BigDecimal The result.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
||||
*/
|
||||
public function power(int $exponent) : BigDecimal
|
||||
{
|
||||
if ($exponent === 0) {
|
||||
return BigDecimal::one();
|
||||
}
|
||||
|
||||
if ($exponent === 1) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($exponent < 0 || $exponent > Calculator::MAX_POWER) {
|
||||
throw new \InvalidArgumentException(\sprintf(
|
||||
'The exponent %d is not in the range 0 to %d.',
|
||||
$exponent,
|
||||
Calculator::MAX_POWER
|
||||
));
|
||||
}
|
||||
|
||||
return new BigDecimal(Calculator::get()->pow($this->value, $exponent), $this->scale * $exponent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient of the division of this number by this given one.
|
||||
*
|
||||
* The quotient has a scale of `0`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @return BigDecimal The quotient.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function quotient($that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->isZero()) {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$p = $this->valueWithMinScale($that->scale);
|
||||
$q = $that->valueWithMinScale($this->scale);
|
||||
|
||||
$quotient = Calculator::get()->divQ($p, $q);
|
||||
|
||||
return new BigDecimal($quotient, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of this number by this given one.
|
||||
*
|
||||
* The remainder has a scale of `max($this->scale, $that->scale)`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @return BigDecimal The remainder.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function remainder($that) : BigDecimal
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->isZero()) {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$p = $this->valueWithMinScale($that->scale);
|
||||
$q = $that->valueWithMinScale($this->scale);
|
||||
|
||||
$remainder = Calculator::get()->divR($p, $q);
|
||||
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
|
||||
return new BigDecimal($remainder, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient and remainder of the division of this number by the given one.
|
||||
*
|
||||
* The quotient has a scale of `0`, and the remainder has a scale of `max($this->scale, $that->scale)`.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor. Must be convertible to a BigDecimal.
|
||||
*
|
||||
* @return BigDecimal[] An array containing the quotient and the remainder.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid decimal number, or is zero.
|
||||
*/
|
||||
public function quotientAndRemainder($that) : array
|
||||
{
|
||||
$that = BigDecimal::of($that);
|
||||
|
||||
if ($that->isZero()) {
|
||||
throw DivisionByZeroException::divisionByZero();
|
||||
}
|
||||
|
||||
$p = $this->valueWithMinScale($that->scale);
|
||||
$q = $that->valueWithMinScale($this->scale);
|
||||
|
||||
[$quotient, $remainder] = Calculator::get()->divQR($p, $q);
|
||||
|
||||
$scale = $this->scale > $that->scale ? $this->scale : $that->scale;
|
||||
|
||||
$quotient = new BigDecimal($quotient, 0);
|
||||
$remainder = new BigDecimal($remainder, $scale);
|
||||
|
||||
return [$quotient, $remainder];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of this number, rounded down to the given number of decimals.
|
||||
*
|
||||
* @param int $scale
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @throws \InvalidArgumentException If the scale is negative.
|
||||
* @throws NegativeNumberException If this number is negative.
|
||||
*/
|
||||
public function sqrt(int $scale) : BigDecimal
|
||||
{
|
||||
if ($scale < 0) {
|
||||
throw new \InvalidArgumentException('Scale cannot be negative.');
|
||||
}
|
||||
|
||||
if ($this->value === '0') {
|
||||
return new BigDecimal('0', $scale);
|
||||
}
|
||||
|
||||
if ($this->value[0] === '-') {
|
||||
throw new NegativeNumberException('Cannot calculate the square root of a negative number.');
|
||||
}
|
||||
|
||||
$value = $this->value;
|
||||
$addDigits = 2 * $scale - $this->scale;
|
||||
|
||||
if ($addDigits > 0) {
|
||||
// add zeros
|
||||
$value .= \str_repeat('0', $addDigits);
|
||||
} elseif ($addDigits < 0) {
|
||||
// trim digits
|
||||
if (-$addDigits >= \strlen($this->value)) {
|
||||
// requesting a scale too low, will always yield a zero result
|
||||
return new BigDecimal('0', $scale);
|
||||
}
|
||||
|
||||
$value = \substr($value, 0, $addDigits);
|
||||
}
|
||||
|
||||
$value = Calculator::get()->sqrt($value);
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this BigDecimal with the decimal point moved $n places to the left.
|
||||
*
|
||||
* @param int $n
|
||||
*
|
||||
* @return BigDecimal
|
||||
*/
|
||||
public function withPointMovedLeft(int $n) : BigDecimal
|
||||
{
|
||||
if ($n === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($n < 0) {
|
||||
return $this->withPointMovedRight(-$n);
|
||||
}
|
||||
|
||||
return new BigDecimal($this->value, $this->scale + $n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this BigDecimal with the decimal point moved $n places to the right.
|
||||
*
|
||||
* @param int $n
|
||||
*
|
||||
* @return BigDecimal
|
||||
*/
|
||||
public function withPointMovedRight(int $n) : BigDecimal
|
||||
{
|
||||
if ($n === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($n < 0) {
|
||||
return $this->withPointMovedLeft(-$n);
|
||||
}
|
||||
|
||||
$value = $this->value;
|
||||
$scale = $this->scale - $n;
|
||||
|
||||
if ($scale < 0) {
|
||||
if ($value !== '0') {
|
||||
$value .= \str_repeat('0', -$scale);
|
||||
}
|
||||
$scale = 0;
|
||||
}
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a copy of this BigDecimal with any trailing zeros removed from the fractional part.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*/
|
||||
public function stripTrailingZeros() : BigDecimal
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$trimmedValue = \rtrim($this->value, '0');
|
||||
|
||||
if ($trimmedValue === '') {
|
||||
return BigDecimal::zero();
|
||||
}
|
||||
|
||||
$trimmableZeros = \strlen($this->value) - \strlen($trimmedValue);
|
||||
|
||||
if ($trimmableZeros === 0) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($trimmableZeros > $this->scale) {
|
||||
$trimmableZeros = $this->scale;
|
||||
}
|
||||
|
||||
$value = \substr($this->value, 0, -$trimmableZeros);
|
||||
$scale = $this->scale - $trimmableZeros;
|
||||
|
||||
return new BigDecimal($value, $scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of this number.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*/
|
||||
public function abs() : BigDecimal
|
||||
{
|
||||
return $this->isNegative() ? $this->negated() : $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this number.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*/
|
||||
public function negated() : BigDecimal
|
||||
{
|
||||
return new BigDecimal(Calculator::get()->neg($this->value), $this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compareTo($that) : int
|
||||
{
|
||||
$that = BigNumber::of($that);
|
||||
|
||||
if ($that instanceof BigInteger) {
|
||||
$that = $that->toBigDecimal();
|
||||
}
|
||||
|
||||
if ($that instanceof BigDecimal) {
|
||||
[$a, $b] = $this->scaleValues($this, $that);
|
||||
|
||||
return Calculator::get()->cmp($a, $b);
|
||||
}
|
||||
|
||||
return - $that->compareTo($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSign() : int
|
||||
{
|
||||
return ($this->value === '0') ? 0 : (($this->value[0] === '-') ? -1 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function getUnscaledValue() : BigInteger
|
||||
{
|
||||
return BigInteger::create($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getScale() : int
|
||||
{
|
||||
return $this->scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the integral part of this decimal number.
|
||||
*
|
||||
* Example: `-123.456` => `-123`.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIntegralPart() : string
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
$value = $this->getUnscaledValueWithLeadingZeros();
|
||||
|
||||
return \substr($value, 0, -$this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representing the fractional part of this decimal number.
|
||||
*
|
||||
* If the scale is zero, an empty string is returned.
|
||||
*
|
||||
* Examples: `-123.456` => '456', `123` => ''.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getFractionalPart() : string
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$value = $this->getUnscaledValueWithLeadingZeros();
|
||||
|
||||
return \substr($value, -$this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this decimal number has a non-zero fractional part.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasNonZeroFractionalPart() : bool
|
||||
{
|
||||
return $this->getFractionalPart() !== \str_repeat('0', $this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigInteger() : BigInteger
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
$zeroScaleDecimal = $this;
|
||||
} else {
|
||||
$zeroScaleDecimal = $this->dividedBy(1, 0);
|
||||
}
|
||||
|
||||
return BigInteger::create($zeroScaleDecimal->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigDecimal() : BigDecimal
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigRational() : BigRational
|
||||
{
|
||||
$numerator = BigInteger::create($this->value);
|
||||
$denominator = BigInteger::create('1' . \str_repeat('0', $this->scale));
|
||||
|
||||
return BigRational::create($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
if ($scale === $this->scale) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return $this->dividedBy(BigDecimal::one(), $scale, $roundingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toInt() : int
|
||||
{
|
||||
return $this->toBigInteger()->toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toFloat() : float
|
||||
{
|
||||
return (float) (string) $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
if ($this->scale === 0) {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
$value = $this->getUnscaledValueWithLeadingZeros();
|
||||
|
||||
return \substr($value, 0, -$this->scale) . '.' . \substr($value, -$this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return $this->value . ':' . $this->scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function unserialize($value) : void
|
||||
{
|
||||
if (isset($this->value)) {
|
||||
throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
|
||||
}
|
||||
|
||||
[$value, $scale] = \explode(':', $value);
|
||||
|
||||
$this->value = $value;
|
||||
$this->scale = (int) $scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the internal values of the given decimal numbers on the same scale.
|
||||
*
|
||||
* @param BigDecimal $x The first decimal number.
|
||||
* @param BigDecimal $y The second decimal number.
|
||||
*
|
||||
* @return array{0: string, 1: string} The scaled integer values of $x and $y.
|
||||
*/
|
||||
private function scaleValues(BigDecimal $x, BigDecimal $y) : array
|
||||
{
|
||||
$a = $x->value;
|
||||
$b = $y->value;
|
||||
|
||||
if ($b !== '0' && $x->scale > $y->scale) {
|
||||
$b .= \str_repeat('0', $x->scale - $y->scale);
|
||||
} elseif ($a !== '0' && $x->scale < $y->scale) {
|
||||
$a .= \str_repeat('0', $y->scale - $x->scale);
|
||||
}
|
||||
|
||||
return [$a, $b];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $scale
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function valueWithMinScale(int $scale) : string
|
||||
{
|
||||
$value = $this->value;
|
||||
|
||||
if ($this->value !== '0' && $scale > $this->scale) {
|
||||
$value .= \str_repeat('0', $scale - $this->scale);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds leading zeros if necessary to the unscaled value to represent the full decimal number.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getUnscaledValueWithLeadingZeros() : string
|
||||
{
|
||||
$value = $this->value;
|
||||
$targetLength = $this->scale + 1;
|
||||
$negative = ($value[0] === '-');
|
||||
$length = \strlen($value);
|
||||
|
||||
if ($negative) {
|
||||
$length--;
|
||||
}
|
||||
|
||||
if ($length >= $targetLength) {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
if ($negative) {
|
||||
$value = \substr($value, 1);
|
||||
}
|
||||
|
||||
$value = \str_pad($value, $targetLength, '0', STR_PAD_LEFT);
|
||||
|
||||
if ($negative) {
|
||||
$value = '-' . $value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
1166
admin/phpMyAdmin/vendor/brick/math/src/BigInteger.php
vendored
Normal file
1166
admin/phpMyAdmin/vendor/brick/math/src/BigInteger.php
vendored
Normal file
File diff suppressed because it is too large
Load diff
528
admin/phpMyAdmin/vendor/brick/math/src/BigNumber.php
vendored
Normal file
528
admin/phpMyAdmin/vendor/brick/math/src/BigNumber.php
vendored
Normal file
|
@ -0,0 +1,528 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math;
|
||||
|
||||
use Brick\Math\Exception\DivisionByZeroException;
|
||||
use Brick\Math\Exception\MathException;
|
||||
use Brick\Math\Exception\NumberFormatException;
|
||||
use Brick\Math\Exception\RoundingNecessaryException;
|
||||
|
||||
/**
|
||||
* Common interface for arbitrary-precision rational numbers.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
abstract class BigNumber implements \Serializable, \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* The regular expression used to parse integer, decimal and rational numbers.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private const PARSE_REGEXP =
|
||||
'/^' .
|
||||
'(?<integral>[\-\+]?[0-9]+)' .
|
||||
'(?:' .
|
||||
'(?:' .
|
||||
'(?:\.(?<fractional>[0-9]+))?' .
|
||||
'(?:[eE](?<exponent>[\-\+]?[0-9]+))?' .
|
||||
')' . '|' . '(?:' .
|
||||
'(?:\/(?<denominator>[0-9]+))?' .
|
||||
')' .
|
||||
')?' .
|
||||
'$/';
|
||||
|
||||
/**
|
||||
* Creates a BigNumber of the given value.
|
||||
*
|
||||
* The concrete return type is dependent on the given value, with the following rules:
|
||||
*
|
||||
* - BigNumber instances are returned as is
|
||||
* - integer numbers are returned as BigInteger
|
||||
* - floating point numbers are converted to a string then parsed as such
|
||||
* - strings containing a `/` character are returned as BigRational
|
||||
* - strings containing a `.` character or using an exponential notation are returned as BigDecimal
|
||||
* - strings containing only digits with an optional leading `+` or `-` sign are returned as BigInteger
|
||||
*
|
||||
* @param BigNumber|int|float|string $value
|
||||
*
|
||||
* @return BigNumber
|
||||
*
|
||||
* @throws NumberFormatException If the format of the number is not valid.
|
||||
* @throws DivisionByZeroException If the value represents a rational number with a denominator of zero.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of($value) : BigNumber
|
||||
{
|
||||
if ($value instanceof BigNumber) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (\is_int($value)) {
|
||||
return new BigInteger((string) $value);
|
||||
}
|
||||
|
||||
if (\is_float($value)) {
|
||||
$value = self::floatToString($value);
|
||||
} else {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
if (\preg_match(self::PARSE_REGEXP, $value, $matches) !== 1) {
|
||||
throw new NumberFormatException(\sprintf('The given value "%s" does not represent a valid number.', $value));
|
||||
}
|
||||
|
||||
if (isset($matches['denominator'])) {
|
||||
$numerator = self::cleanUp($matches['integral']);
|
||||
$denominator = \ltrim($matches['denominator'], '0');
|
||||
|
||||
if ($denominator === '') {
|
||||
throw DivisionByZeroException::denominatorMustNotBeZero();
|
||||
}
|
||||
|
||||
return new BigRational(new BigInteger($numerator), new BigInteger($denominator), false);
|
||||
}
|
||||
|
||||
if (isset($matches['fractional']) || isset($matches['exponent'])) {
|
||||
$fractional = isset($matches['fractional']) ? $matches['fractional'] : '';
|
||||
$exponent = isset($matches['exponent']) ? (int) $matches['exponent'] : 0;
|
||||
|
||||
$unscaledValue = self::cleanUp($matches['integral'] . $fractional);
|
||||
|
||||
$scale = \strlen($fractional) - $exponent;
|
||||
|
||||
if ($scale < 0) {
|
||||
if ($unscaledValue !== '0') {
|
||||
$unscaledValue .= \str_repeat('0', - $scale);
|
||||
}
|
||||
$scale = 0;
|
||||
}
|
||||
|
||||
return new BigDecimal($unscaledValue, $scale);
|
||||
}
|
||||
|
||||
$integral = self::cleanUp($matches['integral']);
|
||||
|
||||
return new BigInteger($integral);
|
||||
}
|
||||
|
||||
/**
|
||||
* Safely converts float to string, avoiding locale-dependent issues.
|
||||
*
|
||||
* @see https://github.com/brick/math/pull/20
|
||||
*
|
||||
* @param float $float
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @psalm-pure
|
||||
* @psalm-suppress ImpureFunctionCall
|
||||
*/
|
||||
private static function floatToString(float $float) : string
|
||||
{
|
||||
$currentLocale = \setlocale(LC_NUMERIC, '0');
|
||||
\setlocale(LC_NUMERIC, 'C');
|
||||
|
||||
$result = (string) $float;
|
||||
|
||||
\setlocale(LC_NUMERIC, $currentLocale);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxy method to access protected constructors from sibling classes.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param mixed ...$args The arguments to the constructor.
|
||||
*
|
||||
* @return static
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
protected static function create(... $args) : BigNumber
|
||||
{
|
||||
/** @psalm-suppress TooManyArguments */
|
||||
return new static(... $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimum of the given values.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
|
||||
* to an instance of the class this method is called on.
|
||||
*
|
||||
* @return static The minimum value.
|
||||
*
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function min(...$values) : BigNumber
|
||||
{
|
||||
$min = null;
|
||||
|
||||
foreach ($values as $value) {
|
||||
$value = static::of($value);
|
||||
|
||||
if ($min === null || $value->isLessThan($min)) {
|
||||
$min = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($min === null) {
|
||||
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
|
||||
}
|
||||
|
||||
return $min;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum of the given values.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The numbers to compare. All the numbers need to be convertible
|
||||
* to an instance of the class this method is called on.
|
||||
*
|
||||
* @return static The maximum value.
|
||||
*
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function max(...$values) : BigNumber
|
||||
{
|
||||
$max = null;
|
||||
|
||||
foreach ($values as $value) {
|
||||
$value = static::of($value);
|
||||
|
||||
if ($max === null || $value->isGreaterThan($max)) {
|
||||
$max = $value;
|
||||
}
|
||||
}
|
||||
|
||||
if ($max === null) {
|
||||
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
|
||||
}
|
||||
|
||||
return $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of the given values.
|
||||
*
|
||||
* @param BigNumber|int|float|string ...$values The numbers to add. All the numbers need to be convertible
|
||||
* to an instance of the class this method is called on.
|
||||
*
|
||||
* @return static The sum.
|
||||
*
|
||||
* @throws \InvalidArgumentException If no values are given.
|
||||
* @throws MathException If an argument is not valid.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function sum(...$values) : BigNumber
|
||||
{
|
||||
/** @var BigNumber|null $sum */
|
||||
$sum = null;
|
||||
|
||||
foreach ($values as $value) {
|
||||
$value = static::of($value);
|
||||
|
||||
if ($sum === null) {
|
||||
$sum = $value;
|
||||
} else {
|
||||
$sum = self::add($sum, $value);
|
||||
}
|
||||
}
|
||||
|
||||
if ($sum === null) {
|
||||
throw new \InvalidArgumentException(__METHOD__ . '() expects at least one value.');
|
||||
}
|
||||
|
||||
return $sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two BigNumber instances in the correct order to avoid a RoundingNecessaryException.
|
||||
*
|
||||
* @todo This could be better resolved by creating an abstract protected method in BigNumber, and leaving to
|
||||
* concrete classes the responsibility to perform the addition themselves or delegate it to the given number,
|
||||
* depending on their ability to perform the operation. This will also require a version bump because we're
|
||||
* potentially breaking custom BigNumber implementations (if any...)
|
||||
*
|
||||
* @param BigNumber $a
|
||||
* @param BigNumber $b
|
||||
*
|
||||
* @return BigNumber
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
private static function add(BigNumber $a, BigNumber $b) : BigNumber
|
||||
{
|
||||
if ($a instanceof BigRational) {
|
||||
return $a->plus($b);
|
||||
}
|
||||
|
||||
if ($b instanceof BigRational) {
|
||||
return $b->plus($a);
|
||||
}
|
||||
|
||||
if ($a instanceof BigDecimal) {
|
||||
return $a->plus($b);
|
||||
}
|
||||
|
||||
if ($b instanceof BigDecimal) {
|
||||
return $b->plus($a);
|
||||
}
|
||||
|
||||
/** @var BigInteger $a */
|
||||
|
||||
return $a->plus($b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes optional leading zeros and + sign from the given number.
|
||||
*
|
||||
* @param string $number The number, validated as a non-empty string of digits with optional sign.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
private static function cleanUp(string $number) : string
|
||||
{
|
||||
$firstChar = $number[0];
|
||||
|
||||
if ($firstChar === '+' || $firstChar === '-') {
|
||||
$number = \substr($number, 1);
|
||||
}
|
||||
|
||||
$number = \ltrim($number, '0');
|
||||
|
||||
if ($number === '') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if ($firstChar === '-') {
|
||||
return '-' . $number;
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is equal to the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isEqualTo($that) : bool
|
||||
{
|
||||
return $this->compareTo($that) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly lower than the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLessThan($that) : bool
|
||||
{
|
||||
return $this->compareTo($that) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is lower than or equal to the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isLessThanOrEqualTo($that) : bool
|
||||
{
|
||||
return $this->compareTo($that) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly greater than the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isGreaterThan($that) : bool
|
||||
{
|
||||
return $this->compareTo($that) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is greater than or equal to the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isGreaterThanOrEqualTo($that) : bool
|
||||
{
|
||||
return $this->compareTo($that) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number equals zero.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isZero() : bool
|
||||
{
|
||||
return $this->getSign() === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly negative.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNegative() : bool
|
||||
{
|
||||
return $this->getSign() < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is negative or zero.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNegativeOrZero() : bool
|
||||
{
|
||||
return $this->getSign() <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is strictly positive.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPositive() : bool
|
||||
{
|
||||
return $this->getSign() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this number is positive or zero.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPositiveOrZero() : bool
|
||||
{
|
||||
return $this->getSign() >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sign of this number.
|
||||
*
|
||||
* @return int -1 if the number is negative, 0 if zero, 1 if positive.
|
||||
*/
|
||||
abstract public function getSign() : int;
|
||||
|
||||
/**
|
||||
* Compares this number to the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that
|
||||
*
|
||||
* @return int [-1,0,1] If `$this` is lower than, equal to, or greater than `$that`.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
abstract public function compareTo($that) : int;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigInteger.
|
||||
*
|
||||
* @return BigInteger The converted number.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to a BigInteger without rounding.
|
||||
*/
|
||||
abstract public function toBigInteger() : BigInteger;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigDecimal.
|
||||
*
|
||||
* @return BigDecimal The converted number.
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to a BigDecimal without rounding.
|
||||
*/
|
||||
abstract public function toBigDecimal() : BigDecimal;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigRational.
|
||||
*
|
||||
* @return BigRational The converted number.
|
||||
*/
|
||||
abstract public function toBigRational() : BigRational;
|
||||
|
||||
/**
|
||||
* Converts this number to a BigDecimal with the given scale, using rounding if necessary.
|
||||
*
|
||||
* @param int $scale The scale of the resulting `BigDecimal`.
|
||||
* @param int $roundingMode A `RoundingMode` constant.
|
||||
*
|
||||
* @return BigDecimal
|
||||
*
|
||||
* @throws RoundingNecessaryException If this number cannot be converted to the given scale without rounding.
|
||||
* This only applies when RoundingMode::UNNECESSARY is used.
|
||||
*/
|
||||
abstract public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal;
|
||||
|
||||
/**
|
||||
* Returns the exact value of this number as a native integer.
|
||||
*
|
||||
* If this number cannot be converted to a native integer without losing precision, an exception is thrown.
|
||||
* Note that the acceptable range for an integer depends on the platform and differs for 32-bit and 64-bit.
|
||||
*
|
||||
* @return int The converted value.
|
||||
*
|
||||
* @throws MathException If this number cannot be exactly converted to a native integer.
|
||||
*/
|
||||
abstract public function toInt() : int;
|
||||
|
||||
/**
|
||||
* Returns an approximation of this number as a floating-point value.
|
||||
*
|
||||
* Note that this method can discard information as the precision of a floating-point value
|
||||
* is inherently limited.
|
||||
*
|
||||
* If the number is greater than the largest representable floating point number, positive infinity is returned.
|
||||
* If the number is less than the smallest representable floating point number, negative infinity is returned.
|
||||
*
|
||||
* @return float The converted value.
|
||||
*/
|
||||
abstract public function toFloat() : float;
|
||||
|
||||
/**
|
||||
* Returns a string representation of this number.
|
||||
*
|
||||
* The output of this method can be parsed by the `of()` factory method;
|
||||
* this will yield an object equal to this one, without any information loss.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract public function __toString() : string;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function jsonSerialize() : string
|
||||
{
|
||||
return $this->__toString();
|
||||
}
|
||||
}
|
479
admin/phpMyAdmin/vendor/brick/math/src/BigRational.php
vendored
Normal file
479
admin/phpMyAdmin/vendor/brick/math/src/BigRational.php
vendored
Normal file
|
@ -0,0 +1,479 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math;
|
||||
|
||||
use Brick\Math\Exception\DivisionByZeroException;
|
||||
use Brick\Math\Exception\MathException;
|
||||
use Brick\Math\Exception\NumberFormatException;
|
||||
use Brick\Math\Exception\RoundingNecessaryException;
|
||||
|
||||
/**
|
||||
* An arbitrarily large rational number.
|
||||
*
|
||||
* This class is immutable.
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
final class BigRational extends BigNumber
|
||||
{
|
||||
/**
|
||||
* The numerator.
|
||||
*
|
||||
* @var BigInteger
|
||||
*/
|
||||
private $numerator;
|
||||
|
||||
/**
|
||||
* The denominator. Always strictly positive.
|
||||
*
|
||||
* @var BigInteger
|
||||
*/
|
||||
private $denominator;
|
||||
|
||||
/**
|
||||
* Protected constructor. Use a factory method to obtain an instance.
|
||||
*
|
||||
* @param BigInteger $numerator The numerator.
|
||||
* @param BigInteger $denominator The denominator.
|
||||
* @param bool $checkDenominator Whether to check the denominator for negative and zero.
|
||||
*
|
||||
* @throws DivisionByZeroException If the denominator is zero.
|
||||
*/
|
||||
protected function __construct(BigInteger $numerator, BigInteger $denominator, bool $checkDenominator)
|
||||
{
|
||||
if ($checkDenominator) {
|
||||
if ($denominator->isZero()) {
|
||||
throw DivisionByZeroException::denominatorMustNotBeZero();
|
||||
}
|
||||
|
||||
if ($denominator->isNegative()) {
|
||||
$numerator = $numerator->negated();
|
||||
$denominator = $denominator->negated();
|
||||
}
|
||||
}
|
||||
|
||||
$this->numerator = $numerator;
|
||||
$this->denominator = $denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigRational of the given value.
|
||||
*
|
||||
* @param BigNumber|int|float|string $value
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @throws MathException If the value cannot be converted to a BigRational.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function of($value) : BigNumber
|
||||
{
|
||||
return parent::of($value)->toBigRational();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a BigRational out of a numerator and a denominator.
|
||||
*
|
||||
* If the denominator is negative, the signs of both the numerator and the denominator
|
||||
* will be inverted to ensure that the denominator is always positive.
|
||||
*
|
||||
* @param BigNumber|int|float|string $numerator The numerator. Must be convertible to a BigInteger.
|
||||
* @param BigNumber|int|float|string $denominator The denominator. Must be convertible to a BigInteger.
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @throws NumberFormatException If an argument does not represent a valid number.
|
||||
* @throws RoundingNecessaryException If an argument represents a non-integer number.
|
||||
* @throws DivisionByZeroException If the denominator is zero.
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function nd($numerator, $denominator) : BigRational
|
||||
{
|
||||
$numerator = BigInteger::of($numerator);
|
||||
$denominator = BigInteger::of($denominator);
|
||||
|
||||
return new BigRational($numerator, $denominator, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigRational representing zero.
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function zero() : BigRational
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $zero;
|
||||
|
||||
if ($zero === null) {
|
||||
$zero = new BigRational(BigInteger::zero(), BigInteger::one(), false);
|
||||
}
|
||||
|
||||
return $zero;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigRational representing one.
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function one() : BigRational
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $one;
|
||||
|
||||
if ($one === null) {
|
||||
$one = new BigRational(BigInteger::one(), BigInteger::one(), false);
|
||||
}
|
||||
|
||||
return $one;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a BigRational representing ten.
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function ten() : BigRational
|
||||
{
|
||||
/** @psalm-suppress ImpureStaticVariable */
|
||||
static $ten;
|
||||
|
||||
if ($ten === null) {
|
||||
$ten = new BigRational(BigInteger::ten(), BigInteger::one(), false);
|
||||
}
|
||||
|
||||
return $ten;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function getNumerator() : BigInteger
|
||||
{
|
||||
return $this->numerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function getDenominator() : BigInteger
|
||||
{
|
||||
return $this->denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient of the division of the numerator by the denominator.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function quotient() : BigInteger
|
||||
{
|
||||
return $this->numerator->quotient($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of the numerator by the denominator.
|
||||
*
|
||||
* @return BigInteger
|
||||
*/
|
||||
public function remainder() : BigInteger
|
||||
{
|
||||
return $this->numerator->remainder($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the quotient and remainder of the division of the numerator by the denominator.
|
||||
*
|
||||
* @return BigInteger[]
|
||||
*/
|
||||
public function quotientAndRemainder() : array
|
||||
{
|
||||
return $this->numerator->quotientAndRemainder($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sum of this number and the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The number to add.
|
||||
*
|
||||
* @return BigRational The result.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
public function plus($that) : BigRational
|
||||
{
|
||||
$that = BigRational::of($that);
|
||||
|
||||
$numerator = $this->numerator->multipliedBy($that->denominator);
|
||||
$numerator = $numerator->plus($that->numerator->multipliedBy($this->denominator));
|
||||
$denominator = $this->denominator->multipliedBy($that->denominator);
|
||||
|
||||
return new BigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the difference of this number and the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The number to subtract.
|
||||
*
|
||||
* @return BigRational The result.
|
||||
*
|
||||
* @throws MathException If the number is not valid.
|
||||
*/
|
||||
public function minus($that) : BigRational
|
||||
{
|
||||
$that = BigRational::of($that);
|
||||
|
||||
$numerator = $this->numerator->multipliedBy($that->denominator);
|
||||
$numerator = $numerator->minus($that->numerator->multipliedBy($this->denominator));
|
||||
$denominator = $this->denominator->multipliedBy($that->denominator);
|
||||
|
||||
return new BigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the product of this number and the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The multiplier.
|
||||
*
|
||||
* @return BigRational The result.
|
||||
*
|
||||
* @throws MathException If the multiplier is not a valid number.
|
||||
*/
|
||||
public function multipliedBy($that) : BigRational
|
||||
{
|
||||
$that = BigRational::of($that);
|
||||
|
||||
$numerator = $this->numerator->multipliedBy($that->numerator);
|
||||
$denominator = $this->denominator->multipliedBy($that->denominator);
|
||||
|
||||
return new BigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of the division of this number by the given one.
|
||||
*
|
||||
* @param BigNumber|int|float|string $that The divisor.
|
||||
*
|
||||
* @return BigRational The result.
|
||||
*
|
||||
* @throws MathException If the divisor is not a valid number, or is zero.
|
||||
*/
|
||||
public function dividedBy($that) : BigRational
|
||||
{
|
||||
$that = BigRational::of($that);
|
||||
|
||||
$numerator = $this->numerator->multipliedBy($that->denominator);
|
||||
$denominator = $this->denominator->multipliedBy($that->numerator);
|
||||
|
||||
return new BigRational($numerator, $denominator, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns this number exponentiated to the given value.
|
||||
*
|
||||
* @param int $exponent The exponent.
|
||||
*
|
||||
* @return BigRational The result.
|
||||
*
|
||||
* @throws \InvalidArgumentException If the exponent is not in the range 0 to 1,000,000.
|
||||
*/
|
||||
public function power(int $exponent) : BigRational
|
||||
{
|
||||
if ($exponent === 0) {
|
||||
$one = BigInteger::one();
|
||||
|
||||
return new BigRational($one, $one, false);
|
||||
}
|
||||
|
||||
if ($exponent === 1) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
return new BigRational(
|
||||
$this->numerator->power($exponent),
|
||||
$this->denominator->power($exponent),
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the reciprocal of this BigRational.
|
||||
*
|
||||
* The reciprocal has the numerator and denominator swapped.
|
||||
*
|
||||
* @return BigRational
|
||||
*
|
||||
* @throws DivisionByZeroException If the numerator is zero.
|
||||
*/
|
||||
public function reciprocal() : BigRational
|
||||
{
|
||||
return new BigRational($this->denominator, $this->numerator, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of this BigRational.
|
||||
*
|
||||
* @return BigRational
|
||||
*/
|
||||
public function abs() : BigRational
|
||||
{
|
||||
return new BigRational($this->numerator->abs(), $this->denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the negated value of this BigRational.
|
||||
*
|
||||
* @return BigRational
|
||||
*/
|
||||
public function negated() : BigRational
|
||||
{
|
||||
return new BigRational($this->numerator->negated(), $this->denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the simplified value of this BigRational.
|
||||
*
|
||||
* @return BigRational
|
||||
*/
|
||||
public function simplified() : BigRational
|
||||
{
|
||||
$gcd = $this->numerator->gcd($this->denominator);
|
||||
|
||||
$numerator = $this->numerator->quotient($gcd);
|
||||
$denominator = $this->denominator->quotient($gcd);
|
||||
|
||||
return new BigRational($numerator, $denominator, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compareTo($that) : int
|
||||
{
|
||||
return $this->minus($that)->getSign();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSign() : int
|
||||
{
|
||||
return $this->numerator->getSign();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigInteger() : BigInteger
|
||||
{
|
||||
$simplified = $this->simplified();
|
||||
|
||||
if (! $simplified->denominator->isEqualTo(1)) {
|
||||
throw new RoundingNecessaryException('This rational number cannot be represented as an integer value without rounding.');
|
||||
}
|
||||
|
||||
return $simplified->numerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigDecimal() : BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->exactlyDividedBy($this->denominator);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBigRational() : BigRational
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toScale(int $scale, int $roundingMode = RoundingMode::UNNECESSARY) : BigDecimal
|
||||
{
|
||||
return $this->numerator->toBigDecimal()->dividedBy($this->denominator, $scale, $roundingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toInt() : int
|
||||
{
|
||||
return $this->toBigInteger()->toInt();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toFloat() : float
|
||||
{
|
||||
return $this->numerator->toFloat() / $this->denominator->toFloat();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function __toString() : string
|
||||
{
|
||||
$numerator = (string) $this->numerator;
|
||||
$denominator = (string) $this->denominator;
|
||||
|
||||
if ($denominator === '1') {
|
||||
return $numerator;
|
||||
}
|
||||
|
||||
return $this->numerator . '/' . $this->denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required by interface Serializable and SHOULD NOT be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function serialize() : string
|
||||
{
|
||||
return $this->numerator . '/' . $this->denominator;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is only here to implement interface Serializable and cannot be accessed directly.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @param string $value
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws \LogicException
|
||||
*/
|
||||
public function unserialize($value) : void
|
||||
{
|
||||
if (isset($this->numerator)) {
|
||||
throw new \LogicException('unserialize() is an internal function, it must not be called directly.');
|
||||
}
|
||||
|
||||
[$numerator, $denominator] = \explode('/', $value);
|
||||
|
||||
$this->numerator = BigInteger::of($numerator);
|
||||
$this->denominator = BigInteger::of($denominator);
|
||||
}
|
||||
}
|
41
admin/phpMyAdmin/vendor/brick/math/src/Exception/DivisionByZeroException.php
vendored
Normal file
41
admin/phpMyAdmin/vendor/brick/math/src/Exception/DivisionByZeroException.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a division by zero occurs.
|
||||
*/
|
||||
class DivisionByZeroException extends MathException
|
||||
{
|
||||
/**
|
||||
* @return DivisionByZeroException
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function divisionByZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('Division by zero.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DivisionByZeroException
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function modulusMustNotBeZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('The modulus must not be zero.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DivisionByZeroException
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function denominatorMustNotBeZero() : DivisionByZeroException
|
||||
{
|
||||
return new self('The denominator of a rational number cannot be zero.');
|
||||
}
|
||||
}
|
27
admin/phpMyAdmin/vendor/brick/math/src/Exception/IntegerOverflowException.php
vendored
Normal file
27
admin/phpMyAdmin/vendor/brick/math/src/Exception/IntegerOverflowException.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
use Brick\Math\BigInteger;
|
||||
|
||||
/**
|
||||
* Exception thrown when an integer overflow occurs.
|
||||
*/
|
||||
class IntegerOverflowException extends MathException
|
||||
{
|
||||
/**
|
||||
* @param BigInteger $value
|
||||
*
|
||||
* @return IntegerOverflowException
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function toIntOverflow(BigInteger $value) : IntegerOverflowException
|
||||
{
|
||||
$message = '%s is out of range %d to %d and cannot be represented as an integer.';
|
||||
|
||||
return new self(\sprintf($message, (string) $value, PHP_INT_MIN, PHP_INT_MAX));
|
||||
}
|
||||
}
|
14
admin/phpMyAdmin/vendor/brick/math/src/Exception/MathException.php
vendored
Normal file
14
admin/phpMyAdmin/vendor/brick/math/src/Exception/MathException.php
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Base class for all math exceptions.
|
||||
*
|
||||
* This class is abstract to ensure that only fine-grained exceptions are thrown throughout the code.
|
||||
*/
|
||||
class MathException extends \RuntimeException
|
||||
{
|
||||
}
|
12
admin/phpMyAdmin/vendor/brick/math/src/Exception/NegativeNumberException.php
vendored
Normal file
12
admin/phpMyAdmin/vendor/brick/math/src/Exception/NegativeNumberException.php
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to perform an unsupported operation, such as a square root, on a negative number.
|
||||
*/
|
||||
class NegativeNumberException extends MathException
|
||||
{
|
||||
}
|
35
admin/phpMyAdmin/vendor/brick/math/src/Exception/NumberFormatException.php
vendored
Normal file
35
admin/phpMyAdmin/vendor/brick/math/src/Exception/NumberFormatException.php
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when attempting to create a number from a string with an invalid format.
|
||||
*/
|
||||
class NumberFormatException extends MathException
|
||||
{
|
||||
/**
|
||||
* @param string $char The failing character.
|
||||
*
|
||||
* @return NumberFormatException
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function charNotInAlphabet(string $char) : self
|
||||
{
|
||||
$ord = \ord($char);
|
||||
|
||||
if ($ord < 32 || $ord > 126) {
|
||||
$char = \strtoupper(\dechex($ord));
|
||||
|
||||
if ($ord < 10) {
|
||||
$char = '0' . $char;
|
||||
}
|
||||
} else {
|
||||
$char = '"' . $char . '"';
|
||||
}
|
||||
|
||||
return new self(sprintf('Char %s is not a valid character in the given alphabet.', $char));
|
||||
}
|
||||
}
|
21
admin/phpMyAdmin/vendor/brick/math/src/Exception/RoundingNecessaryException.php
vendored
Normal file
21
admin/phpMyAdmin/vendor/brick/math/src/Exception/RoundingNecessaryException.php
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Exception;
|
||||
|
||||
/**
|
||||
* Exception thrown when a number cannot be represented at the requested scale without rounding.
|
||||
*/
|
||||
class RoundingNecessaryException extends MathException
|
||||
{
|
||||
/**
|
||||
* @return RoundingNecessaryException
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function roundingNecessary() : RoundingNecessaryException
|
||||
{
|
||||
return new self('Rounding is necessary to represent the result of the operation at this scale.');
|
||||
}
|
||||
}
|
756
admin/phpMyAdmin/vendor/brick/math/src/Internal/Calculator.php
vendored
Normal file
756
admin/phpMyAdmin/vendor/brick/math/src/Internal/Calculator.php
vendored
Normal file
|
@ -0,0 +1,756 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Internal;
|
||||
|
||||
use Brick\Math\Exception\RoundingNecessaryException;
|
||||
use Brick\Math\RoundingMode;
|
||||
|
||||
/**
|
||||
* Performs basic operations on arbitrary size integers.
|
||||
*
|
||||
* Unless otherwise specified, all parameters must be validated as non-empty strings of digits,
|
||||
* without leading zero, and with an optional leading minus sign if the number is not zero.
|
||||
*
|
||||
* Any other parameter format will lead to undefined behaviour.
|
||||
* All methods must return strings respecting this format, unless specified otherwise.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
abstract class Calculator
|
||||
{
|
||||
/**
|
||||
* The maximum exponent value allowed for the pow() method.
|
||||
*/
|
||||
public const MAX_POWER = 1000000;
|
||||
|
||||
/**
|
||||
* The alphabet for converting from and to base 2 to 36, lowercase.
|
||||
*/
|
||||
public const ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz';
|
||||
|
||||
/**
|
||||
* The Calculator instance in use.
|
||||
*
|
||||
* @var Calculator|null
|
||||
*/
|
||||
private static $instance;
|
||||
|
||||
/**
|
||||
* Sets the Calculator instance to use.
|
||||
*
|
||||
* An instance is typically set only in unit tests: the autodetect is usually the best option.
|
||||
*
|
||||
* @param Calculator|null $calculator The calculator instance, or NULL to revert to autodetect.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
final public static function set(?Calculator $calculator) : void
|
||||
{
|
||||
self::$instance = $calculator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Calculator instance to use.
|
||||
*
|
||||
* If none has been explicitly set, the fastest available implementation will be returned.
|
||||
*
|
||||
* @return Calculator
|
||||
*
|
||||
* @psalm-pure
|
||||
* @psalm-suppress ImpureStaticProperty
|
||||
*/
|
||||
final public static function get() : Calculator
|
||||
{
|
||||
if (self::$instance === null) {
|
||||
/** @psalm-suppress ImpureMethodCall */
|
||||
self::$instance = self::detect();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fastest available Calculator implementation.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @return Calculator
|
||||
*/
|
||||
private static function detect() : Calculator
|
||||
{
|
||||
if (\extension_loaded('gmp')) {
|
||||
return new Calculator\GmpCalculator();
|
||||
}
|
||||
|
||||
if (\extension_loaded('bcmath')) {
|
||||
return new Calculator\BcMathCalculator();
|
||||
}
|
||||
|
||||
return new Calculator\NativeCalculator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the sign & digits of the operands.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return array{0: bool, 1: bool, 2: string, 3: string} Whether $a and $b are negative, followed by their digits.
|
||||
*/
|
||||
final protected function init(string $a, string $b) : array
|
||||
{
|
||||
return [
|
||||
$aNeg = ($a[0] === '-'),
|
||||
$bNeg = ($b[0] === '-'),
|
||||
|
||||
$aNeg ? \substr($a, 1) : $a,
|
||||
$bNeg ? \substr($b, 1) : $b,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the absolute value of a number.
|
||||
*
|
||||
* @param string $n The number.
|
||||
*
|
||||
* @return string The absolute value.
|
||||
*/
|
||||
final public function abs(string $n) : string
|
||||
{
|
||||
return ($n[0] === '-') ? \substr($n, 1) : $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Negates a number.
|
||||
*
|
||||
* @param string $n The number.
|
||||
*
|
||||
* @return string The negated value.
|
||||
*/
|
||||
final public function neg(string $n) : string
|
||||
{
|
||||
if ($n === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if ($n[0] === '-') {
|
||||
return \substr($n, 1);
|
||||
}
|
||||
|
||||
return '-' . $n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two numbers.
|
||||
*
|
||||
* @param string $a The first number.
|
||||
* @param string $b The second number.
|
||||
*
|
||||
* @return int [-1, 0, 1] If the first number is less than, equal to, or greater than the second number.
|
||||
*/
|
||||
final public function cmp(string $a, string $b) : int
|
||||
{
|
||||
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
|
||||
|
||||
if ($aNeg && ! $bNeg) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ($bNeg && ! $aNeg) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
$aLen = \strlen($aDig);
|
||||
$bLen = \strlen($bDig);
|
||||
|
||||
if ($aLen < $bLen) {
|
||||
$result = -1;
|
||||
} elseif ($aLen > $bLen) {
|
||||
$result = 1;
|
||||
} else {
|
||||
$result = $aDig <=> $bDig;
|
||||
}
|
||||
|
||||
return $aNeg ? -$result : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds two numbers.
|
||||
*
|
||||
* @param string $a The augend.
|
||||
* @param string $b The addend.
|
||||
*
|
||||
* @return string The sum.
|
||||
*/
|
||||
abstract public function add(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Subtracts two numbers.
|
||||
*
|
||||
* @param string $a The minuend.
|
||||
* @param string $b The subtrahend.
|
||||
*
|
||||
* @return string The difference.
|
||||
*/
|
||||
abstract public function sub(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Multiplies two numbers.
|
||||
*
|
||||
* @param string $a The multiplicand.
|
||||
* @param string $b The multiplier.
|
||||
*
|
||||
* @return string The product.
|
||||
*/
|
||||
abstract public function mul(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Returns the quotient of the division of two numbers.
|
||||
*
|
||||
* @param string $a The dividend.
|
||||
* @param string $b The divisor, must not be zero.
|
||||
*
|
||||
* @return string The quotient.
|
||||
*/
|
||||
abstract public function divQ(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Returns the remainder of the division of two numbers.
|
||||
*
|
||||
* @param string $a The dividend.
|
||||
* @param string $b The divisor, must not be zero.
|
||||
*
|
||||
* @return string The remainder.
|
||||
*/
|
||||
abstract public function divR(string $a, string $b) : string;
|
||||
|
||||
/**
|
||||
* Returns the quotient and remainder of the division of two numbers.
|
||||
*
|
||||
* @param string $a The dividend.
|
||||
* @param string $b The divisor, must not be zero.
|
||||
*
|
||||
* @return string[] An array containing the quotient and remainder.
|
||||
*/
|
||||
abstract public function divQR(string $a, string $b) : array;
|
||||
|
||||
/**
|
||||
* Exponentiates a number.
|
||||
*
|
||||
* @param string $a The base number.
|
||||
* @param int $e The exponent, validated as an integer between 0 and MAX_POWER.
|
||||
*
|
||||
* @return string The power.
|
||||
*/
|
||||
abstract public function pow(string $a, int $e) : string;
|
||||
|
||||
/**
|
||||
* @param string $a
|
||||
* @param string $b The modulus; must not be zero.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function mod(string $a, string $b) : string
|
||||
{
|
||||
return $this->divR($this->add($this->divR($a, $b), $b), $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the modular multiplicative inverse of $x modulo $m.
|
||||
*
|
||||
* If $x has no multiplicative inverse mod m, this method must return null.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library has built-in support.
|
||||
*
|
||||
* @param string $x
|
||||
* @param string $m The modulus; must not be negative or zero.
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
public function modInverse(string $x, string $m) : ?string
|
||||
{
|
||||
if ($m === '1') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
$modVal = $x;
|
||||
|
||||
if ($x[0] === '-' || ($this->cmp($this->abs($x), $m) >= 0)) {
|
||||
$modVal = $this->mod($x, $m);
|
||||
}
|
||||
|
||||
$x = '0';
|
||||
$y = '0';
|
||||
$g = $this->gcdExtended($modVal, $m, $x, $y);
|
||||
|
||||
if ($g !== '1') {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->mod($this->add($this->mod($x, $m), $m), $m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Raises a number into power with modulo.
|
||||
*
|
||||
* @param string $base The base number; must be positive or zero.
|
||||
* @param string $exp The exponent; must be positive or zero.
|
||||
* @param string $mod The modulus; must be strictly positive.
|
||||
*
|
||||
* @return string The power.
|
||||
*/
|
||||
abstract public function modPow(string $base, string $exp, string $mod) : string;
|
||||
|
||||
/**
|
||||
* Returns the greatest common divisor of the two numbers.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for GCD calculations.
|
||||
*
|
||||
* @param string $a The first number.
|
||||
* @param string $b The second number.
|
||||
*
|
||||
* @return string The GCD, always positive, or zero if both arguments are zero.
|
||||
*/
|
||||
public function gcd(string $a, string $b) : string
|
||||
{
|
||||
if ($a === '0') {
|
||||
return $this->abs($b);
|
||||
}
|
||||
|
||||
if ($b === '0') {
|
||||
return $this->abs($a);
|
||||
}
|
||||
|
||||
return $this->gcd($b, $this->divR($a, $b));
|
||||
}
|
||||
|
||||
private function gcdExtended(string $a, string $b, string &$x, string &$y) : string
|
||||
{
|
||||
if ($a === '0') {
|
||||
$x = '0';
|
||||
$y = '1';
|
||||
|
||||
return $b;
|
||||
}
|
||||
|
||||
$x1 = '0';
|
||||
$y1 = '0';
|
||||
|
||||
$gcd = $this->gcdExtended($this->mod($b, $a), $a, $x1, $y1);
|
||||
|
||||
$x = $this->sub($y1, $this->mul($this->divQ($b, $a), $x1));
|
||||
$y = $x1;
|
||||
|
||||
return $gcd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square root of the given number, rounded down.
|
||||
*
|
||||
* The result is the largest x such that x² ≤ n.
|
||||
* The input MUST NOT be negative.
|
||||
*
|
||||
* @param string $n The number.
|
||||
*
|
||||
* @return string The square root.
|
||||
*/
|
||||
abstract public function sqrt(string $n) : string;
|
||||
|
||||
/**
|
||||
* Converts a number from an arbitrary base.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for base conversion.
|
||||
*
|
||||
* @param string $number The number, positive or zero, non-empty, case-insensitively validated for the given base.
|
||||
* @param int $base The base of the number, validated from 2 to 36.
|
||||
*
|
||||
* @return string The converted number, following the Calculator conventions.
|
||||
*/
|
||||
public function fromBase(string $number, int $base) : string
|
||||
{
|
||||
return $this->fromArbitraryBase(\strtolower($number), self::ALPHABET, $base);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a number to an arbitrary base.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for base conversion.
|
||||
*
|
||||
* @param string $number The number to convert, following the Calculator conventions.
|
||||
* @param int $base The base to convert to, validated from 2 to 36.
|
||||
*
|
||||
* @return string The converted number, lowercase.
|
||||
*/
|
||||
public function toBase(string $number, int $base) : string
|
||||
{
|
||||
$negative = ($number[0] === '-');
|
||||
|
||||
if ($negative) {
|
||||
$number = \substr($number, 1);
|
||||
}
|
||||
|
||||
$number = $this->toArbitraryBase($number, self::ALPHABET, $base);
|
||||
|
||||
if ($negative) {
|
||||
return '-' . $number;
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a non-negative number in an arbitrary base using a custom alphabet, to base 10.
|
||||
*
|
||||
* @param string $number The number to convert, validated as a non-empty string,
|
||||
* containing only chars in the given alphabet/base.
|
||||
* @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum.
|
||||
* @param int $base The base of the number, validated from 2 to alphabet length.
|
||||
*
|
||||
* @return string The number in base 10, following the Calculator conventions.
|
||||
*/
|
||||
final public function fromArbitraryBase(string $number, string $alphabet, int $base) : string
|
||||
{
|
||||
// remove leading "zeros"
|
||||
$number = \ltrim($number, $alphabet[0]);
|
||||
|
||||
if ($number === '') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// optimize for "one"
|
||||
if ($number === $alphabet[1]) {
|
||||
return '1';
|
||||
}
|
||||
|
||||
$result = '0';
|
||||
$power = '1';
|
||||
|
||||
$base = (string) $base;
|
||||
|
||||
for ($i = \strlen($number) - 1; $i >= 0; $i--) {
|
||||
$index = \strpos($alphabet, $number[$i]);
|
||||
|
||||
if ($index !== 0) {
|
||||
$result = $this->add($result, ($index === 1)
|
||||
? $power
|
||||
: $this->mul($power, (string) $index)
|
||||
);
|
||||
}
|
||||
|
||||
if ($i !== 0) {
|
||||
$power = $this->mul($power, $base);
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a non-negative number to an arbitrary base using a custom alphabet.
|
||||
*
|
||||
* @param string $number The number to convert, positive or zero, following the Calculator conventions.
|
||||
* @param string $alphabet The alphabet that contains every digit, validated as 2 chars minimum.
|
||||
* @param int $base The base to convert to, validated from 2 to alphabet length.
|
||||
*
|
||||
* @return string The converted number in the given alphabet.
|
||||
*/
|
||||
final public function toArbitraryBase(string $number, string $alphabet, int $base) : string
|
||||
{
|
||||
if ($number === '0') {
|
||||
return $alphabet[0];
|
||||
}
|
||||
|
||||
$base = (string) $base;
|
||||
$result = '';
|
||||
|
||||
while ($number !== '0') {
|
||||
[$number, $remainder] = $this->divQR($number, $base);
|
||||
$remainder = (int) $remainder;
|
||||
|
||||
$result .= $alphabet[$remainder];
|
||||
}
|
||||
|
||||
return \strrev($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a rounded division.
|
||||
*
|
||||
* Rounding is performed when the remainder of the division is not zero.
|
||||
*
|
||||
* @param string $a The dividend.
|
||||
* @param string $b The divisor.
|
||||
* @param int $roundingMode The rounding mode.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws \InvalidArgumentException If the rounding mode is invalid.
|
||||
* @throws RoundingNecessaryException If RoundingMode::UNNECESSARY is provided but rounding is necessary.
|
||||
*/
|
||||
final public function divRound(string $a, string $b, int $roundingMode) : string
|
||||
{
|
||||
[$quotient, $remainder] = $this->divQR($a, $b);
|
||||
|
||||
$hasDiscardedFraction = ($remainder !== '0');
|
||||
$isPositiveOrZero = ($a[0] === '-') === ($b[0] === '-');
|
||||
|
||||
$discardedFractionSign = function() use ($remainder, $b) : int {
|
||||
$r = $this->abs($this->mul($remainder, '2'));
|
||||
$b = $this->abs($b);
|
||||
|
||||
return $this->cmp($r, $b);
|
||||
};
|
||||
|
||||
$increment = false;
|
||||
|
||||
switch ($roundingMode) {
|
||||
case RoundingMode::UNNECESSARY:
|
||||
if ($hasDiscardedFraction) {
|
||||
throw RoundingNecessaryException::roundingNecessary();
|
||||
}
|
||||
break;
|
||||
|
||||
case RoundingMode::UP:
|
||||
$increment = $hasDiscardedFraction;
|
||||
break;
|
||||
|
||||
case RoundingMode::DOWN:
|
||||
break;
|
||||
|
||||
case RoundingMode::CEILING:
|
||||
$increment = $hasDiscardedFraction && $isPositiveOrZero;
|
||||
break;
|
||||
|
||||
case RoundingMode::FLOOR:
|
||||
$increment = $hasDiscardedFraction && ! $isPositiveOrZero;
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_UP:
|
||||
$increment = $discardedFractionSign() >= 0;
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_DOWN:
|
||||
$increment = $discardedFractionSign() > 0;
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_CEILING:
|
||||
$increment = $isPositiveOrZero ? $discardedFractionSign() >= 0 : $discardedFractionSign() > 0;
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_FLOOR:
|
||||
$increment = $isPositiveOrZero ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
|
||||
break;
|
||||
|
||||
case RoundingMode::HALF_EVEN:
|
||||
$lastDigit = (int) $quotient[-1];
|
||||
$lastDigitIsEven = ($lastDigit % 2 === 0);
|
||||
$increment = $lastDigitIsEven ? $discardedFractionSign() > 0 : $discardedFractionSign() >= 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid rounding mode.');
|
||||
}
|
||||
|
||||
if ($increment) {
|
||||
return $this->add($quotient, $isPositiveOrZero ? '1' : '-1');
|
||||
}
|
||||
|
||||
return $quotient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates bitwise AND of two numbers.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for bitwise operations.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function and(string $a, string $b) : string
|
||||
{
|
||||
return $this->bitwise('and', $a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates bitwise OR of two numbers.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for bitwise operations.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function or(string $a, string $b) : string
|
||||
{
|
||||
return $this->bitwise('or', $a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates bitwise XOR of two numbers.
|
||||
*
|
||||
* This method can be overridden by the concrete implementation if the underlying library
|
||||
* has built-in support for bitwise operations.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function xor(string $a, string $b) : string
|
||||
{
|
||||
return $this->bitwise('xor', $a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a bitwise operation on a decimal number.
|
||||
*
|
||||
* @param string $operator The operator to use, must be "and", "or" or "xor".
|
||||
* @param string $a The left operand.
|
||||
* @param string $b The right operand.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function bitwise(string $operator, string $a, string $b) : string
|
||||
{
|
||||
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
|
||||
|
||||
$aBin = $this->toBinary($aDig);
|
||||
$bBin = $this->toBinary($bDig);
|
||||
|
||||
$aLen = \strlen($aBin);
|
||||
$bLen = \strlen($bBin);
|
||||
|
||||
if ($aLen > $bLen) {
|
||||
$bBin = \str_repeat("\x00", $aLen - $bLen) . $bBin;
|
||||
} elseif ($bLen > $aLen) {
|
||||
$aBin = \str_repeat("\x00", $bLen - $aLen) . $aBin;
|
||||
}
|
||||
|
||||
if ($aNeg) {
|
||||
$aBin = $this->twosComplement($aBin);
|
||||
}
|
||||
if ($bNeg) {
|
||||
$bBin = $this->twosComplement($bBin);
|
||||
}
|
||||
|
||||
switch ($operator) {
|
||||
case 'and':
|
||||
$value = $aBin & $bBin;
|
||||
$negative = ($aNeg and $bNeg);
|
||||
break;
|
||||
|
||||
case 'or':
|
||||
$value = $aBin | $bBin;
|
||||
$negative = ($aNeg or $bNeg);
|
||||
break;
|
||||
|
||||
case 'xor':
|
||||
$value = $aBin ^ $bBin;
|
||||
$negative = ($aNeg xor $bNeg);
|
||||
break;
|
||||
|
||||
// @codeCoverageIgnoreStart
|
||||
default:
|
||||
throw new \InvalidArgumentException('Invalid bitwise operator.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
if ($negative) {
|
||||
$value = $this->twosComplement($value);
|
||||
}
|
||||
|
||||
$result = $this->toDecimal($value);
|
||||
|
||||
return $negative ? $this->neg($result) : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number A positive, binary number.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function twosComplement(string $number) : string
|
||||
{
|
||||
$xor = \str_repeat("\xff", \strlen($number));
|
||||
|
||||
$number = $number ^ $xor;
|
||||
|
||||
for ($i = \strlen($number) - 1; $i >= 0; $i--) {
|
||||
$byte = \ord($number[$i]);
|
||||
|
||||
if (++$byte !== 256) {
|
||||
$number[$i] = \chr($byte);
|
||||
break;
|
||||
}
|
||||
|
||||
$number[$i] = "\x00";
|
||||
|
||||
if ($i === 0) {
|
||||
$number = "\x01" . $number;
|
||||
}
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a decimal number to a binary string.
|
||||
*
|
||||
* @param string $number The number to convert, positive or zero, only digits.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function toBinary(string $number) : string
|
||||
{
|
||||
$result = '';
|
||||
|
||||
while ($number !== '0') {
|
||||
[$number, $remainder] = $this->divQR($number, '256');
|
||||
$result .= \chr((int) $remainder);
|
||||
}
|
||||
|
||||
return \strrev($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the positive decimal representation of a binary number.
|
||||
*
|
||||
* @param string $bytes The bytes representing the number.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function toDecimal(string $bytes) : string
|
||||
{
|
||||
$result = '0';
|
||||
$power = '1';
|
||||
|
||||
for ($i = \strlen($bytes) - 1; $i >= 0; $i--) {
|
||||
$index = \ord($bytes[$i]);
|
||||
|
||||
if ($index !== 0) {
|
||||
$result = $this->add($result, ($index === 1)
|
||||
? $power
|
||||
: $this->mul($power, (string) $index)
|
||||
);
|
||||
}
|
||||
|
||||
if ($i !== 0) {
|
||||
$power = $this->mul($power, '256');
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
92
admin/phpMyAdmin/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
vendored
Normal file
92
admin/phpMyAdmin/vendor/brick/math/src/Internal/Calculator/BcMathCalculator.php
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Internal\Calculator;
|
||||
|
||||
use Brick\Math\Internal\Calculator;
|
||||
|
||||
/**
|
||||
* Calculator implementation built around the bcmath library.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class BcMathCalculator extends Calculator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
return \bcadd($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return \bcsub($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
return \bcmul($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return \bcdiv($a, $b, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divR(string $a, string $b) : string
|
||||
{
|
||||
return \bcmod($a, $b);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQR(string $a, string $b) : array
|
||||
{
|
||||
$q = \bcdiv($a, $b, 0);
|
||||
$r = \bcmod($a, $b);
|
||||
|
||||
return [$q, $r];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function pow(string $a, int $e) : string
|
||||
{
|
||||
return \bcpow($a, (string) $e, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function modPow(string $base, string $exp, string $mod) : string
|
||||
{
|
||||
return \bcpowmod($base, $exp, $mod, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
return \bcsqrt($n, 0);
|
||||
}
|
||||
}
|
156
admin/phpMyAdmin/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
vendored
Normal file
156
admin/phpMyAdmin/vendor/brick/math/src/Internal/Calculator/GmpCalculator.php
vendored
Normal file
|
@ -0,0 +1,156 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Internal\Calculator;
|
||||
|
||||
use Brick\Math\Internal\Calculator;
|
||||
|
||||
/**
|
||||
* Calculator implementation built around the GMP library.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class GmpCalculator extends Calculator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_add($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_sub($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_mul($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_div_q($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divR(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_div_r($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQR(string $a, string $b) : array
|
||||
{
|
||||
[$q, $r] = \gmp_div_qr($a, $b);
|
||||
|
||||
return [
|
||||
\gmp_strval($q),
|
||||
\gmp_strval($r)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function pow(string $a, int $e) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_pow($a, $e));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function modInverse(string $x, string $m) : ?string
|
||||
{
|
||||
$result = \gmp_invert($x, $m);
|
||||
|
||||
if ($result === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return \gmp_strval($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function modPow(string $base, string $exp, string $mod) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_powm($base, $exp, $mod));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function gcd(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_gcd($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function fromBase(string $number, int $base) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_init($number, $base));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function toBase(string $number, int $base) : string
|
||||
{
|
||||
return \gmp_strval($number, $base);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function and(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_and($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function or(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_or($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function xor(string $a, string $b) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_xor($a, $b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
return \gmp_strval(\gmp_sqrt($n));
|
||||
}
|
||||
}
|
616
admin/phpMyAdmin/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
vendored
Normal file
616
admin/phpMyAdmin/vendor/brick/math/src/Internal/Calculator/NativeCalculator.php
vendored
Normal file
|
@ -0,0 +1,616 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math\Internal\Calculator;
|
||||
|
||||
use Brick\Math\Internal\Calculator;
|
||||
|
||||
/**
|
||||
* Calculator implementation using only native PHP code.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
class NativeCalculator extends Calculator
|
||||
{
|
||||
/**
|
||||
* The max number of digits the platform can natively add, subtract, multiply or divide without overflow.
|
||||
* For multiplication, this represents the max sum of the lengths of both operands.
|
||||
*
|
||||
* For addition, it is assumed that an extra digit can hold a carry (1) without overflowing.
|
||||
* Example: 32-bit: max number 1,999,999,999 (9 digits + carry)
|
||||
* 64-bit: max number 1,999,999,999,999,999,999 (18 digits + carry)
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $maxDigits;
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
switch (PHP_INT_SIZE) {
|
||||
case 4:
|
||||
$this->maxDigits = 9;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
$this->maxDigits = 18;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \RuntimeException('The platform is not 32-bit or 64-bit as expected.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add(string $a, string $b) : string
|
||||
{
|
||||
$result = $a + $b;
|
||||
|
||||
if (is_int($result)) {
|
||||
return (string) $result;
|
||||
}
|
||||
|
||||
if ($a === '0') {
|
||||
return $b;
|
||||
}
|
||||
|
||||
if ($b === '0') {
|
||||
return $a;
|
||||
}
|
||||
|
||||
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
|
||||
|
||||
if ($aNeg === $bNeg) {
|
||||
$result = $this->doAdd($aDig, $bDig);
|
||||
} else {
|
||||
$result = $this->doSub($aDig, $bDig);
|
||||
}
|
||||
|
||||
if ($aNeg) {
|
||||
$result = $this->neg($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function sub(string $a, string $b) : string
|
||||
{
|
||||
return $this->add($a, $this->neg($b));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mul(string $a, string $b) : string
|
||||
{
|
||||
$result = $a * $b;
|
||||
|
||||
if (is_int($result)) {
|
||||
return (string) $result;
|
||||
}
|
||||
|
||||
if ($a === '0' || $b === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if ($a === '1') {
|
||||
return $b;
|
||||
}
|
||||
|
||||
if ($b === '1') {
|
||||
return $a;
|
||||
}
|
||||
|
||||
if ($a === '-1') {
|
||||
return $this->neg($b);
|
||||
}
|
||||
|
||||
if ($b === '-1') {
|
||||
return $this->neg($a);
|
||||
}
|
||||
|
||||
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
|
||||
|
||||
$result = $this->doMul($aDig, $bDig);
|
||||
|
||||
if ($aNeg !== $bNeg) {
|
||||
$result = $this->neg($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQ(string $a, string $b) : string
|
||||
{
|
||||
return $this->divQR($a, $b)[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divR(string $a, string $b): string
|
||||
{
|
||||
return $this->divQR($a, $b)[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divQR(string $a, string $b) : array
|
||||
{
|
||||
if ($a === '0') {
|
||||
return ['0', '0'];
|
||||
}
|
||||
|
||||
if ($a === $b) {
|
||||
return ['1', '0'];
|
||||
}
|
||||
|
||||
if ($b === '1') {
|
||||
return [$a, '0'];
|
||||
}
|
||||
|
||||
if ($b === '-1') {
|
||||
return [$this->neg($a), '0'];
|
||||
}
|
||||
|
||||
$na = $a * 1; // cast to number
|
||||
|
||||
if (is_int($na)) {
|
||||
$nb = $b * 1;
|
||||
|
||||
if (is_int($nb)) {
|
||||
// the only division that may overflow is PHP_INT_MIN / -1,
|
||||
// which cannot happen here as we've already handled a divisor of -1 above.
|
||||
$r = $na % $nb;
|
||||
$q = ($na - $r) / $nb;
|
||||
|
||||
assert(is_int($q));
|
||||
|
||||
return [
|
||||
(string) $q,
|
||||
(string) $r
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
[$aNeg, $bNeg, $aDig, $bDig] = $this->init($a, $b);
|
||||
|
||||
[$q, $r] = $this->doDiv($aDig, $bDig);
|
||||
|
||||
if ($aNeg !== $bNeg) {
|
||||
$q = $this->neg($q);
|
||||
}
|
||||
|
||||
if ($aNeg) {
|
||||
$r = $this->neg($r);
|
||||
}
|
||||
|
||||
return [$q, $r];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function pow(string $a, int $e) : string
|
||||
{
|
||||
if ($e === 0) {
|
||||
return '1';
|
||||
}
|
||||
|
||||
if ($e === 1) {
|
||||
return $a;
|
||||
}
|
||||
|
||||
$odd = $e % 2;
|
||||
$e -= $odd;
|
||||
|
||||
$aa = $this->mul($a, $a);
|
||||
$result = $this->pow($aa, $e / 2);
|
||||
|
||||
if ($odd === 1) {
|
||||
$result = $this->mul($result, $a);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Algorithm from: https://www.geeksforgeeks.org/modular-exponentiation-power-in-modular-arithmetic/
|
||||
*
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function modPow(string $base, string $exp, string $mod) : string
|
||||
{
|
||||
// special case: the algorithm below fails with 0 power 0 mod 1 (returns 1 instead of 0)
|
||||
if ($base === '0' && $exp === '0' && $mod === '1') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// special case: the algorithm below fails with power 0 mod 1 (returns 1 instead of 0)
|
||||
if ($exp === '0' && $mod === '1') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
$x = $base;
|
||||
|
||||
$res = '1';
|
||||
|
||||
// numbers are positive, so we can use remainder instead of modulo
|
||||
$x = $this->divR($x, $mod);
|
||||
|
||||
while ($exp !== '0') {
|
||||
if (in_array($exp[-1], ['1', '3', '5', '7', '9'])) { // odd
|
||||
$res = $this->divR($this->mul($res, $x), $mod);
|
||||
}
|
||||
|
||||
$exp = $this->divQ($exp, '2');
|
||||
$x = $this->divR($this->mul($x, $x), $mod);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapted from https://cp-algorithms.com/num_methods/roots_newton.html
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function sqrt(string $n) : string
|
||||
{
|
||||
if ($n === '0') {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// initial approximation
|
||||
$x = \str_repeat('9', \intdiv(\strlen($n), 2) ?: 1);
|
||||
|
||||
$decreased = false;
|
||||
|
||||
for (;;) {
|
||||
$nx = $this->divQ($this->add($x, $this->divQ($n, $x)), '2');
|
||||
|
||||
if ($x === $nx || $this->cmp($nx, $x) > 0 && $decreased) {
|
||||
break;
|
||||
}
|
||||
|
||||
$decreased = $this->cmp($nx, $x) < 0;
|
||||
$x = $nx;
|
||||
}
|
||||
|
||||
return $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the addition of two non-signed large integers.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function doAdd(string $a, string $b) : string
|
||||
{
|
||||
[$a, $b, $length] = $this->pad($a, $b);
|
||||
|
||||
$carry = 0;
|
||||
$result = '';
|
||||
|
||||
for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) {
|
||||
$blockLength = $this->maxDigits;
|
||||
|
||||
if ($i < 0) {
|
||||
$blockLength += $i;
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
$blockA = \substr($a, $i, $blockLength);
|
||||
$blockB = \substr($b, $i, $blockLength);
|
||||
|
||||
$sum = (string) ($blockA + $blockB + $carry);
|
||||
$sumLength = \strlen($sum);
|
||||
|
||||
if ($sumLength > $blockLength) {
|
||||
$sum = \substr($sum, 1);
|
||||
$carry = 1;
|
||||
} else {
|
||||
if ($sumLength < $blockLength) {
|
||||
$sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
|
||||
}
|
||||
$carry = 0;
|
||||
}
|
||||
|
||||
$result = $sum . $result;
|
||||
|
||||
if ($i === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($carry === 1) {
|
||||
$result = '1' . $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the subtraction of two non-signed large integers.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function doSub(string $a, string $b) : string
|
||||
{
|
||||
if ($a === $b) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
// Ensure that we always subtract to a positive result: biggest minus smallest.
|
||||
$cmp = $this->doCmp($a, $b);
|
||||
|
||||
$invert = ($cmp === -1);
|
||||
|
||||
if ($invert) {
|
||||
$c = $a;
|
||||
$a = $b;
|
||||
$b = $c;
|
||||
}
|
||||
|
||||
[$a, $b, $length] = $this->pad($a, $b);
|
||||
|
||||
$carry = 0;
|
||||
$result = '';
|
||||
|
||||
$complement = 10 ** $this->maxDigits;
|
||||
|
||||
for ($i = $length - $this->maxDigits;; $i -= $this->maxDigits) {
|
||||
$blockLength = $this->maxDigits;
|
||||
|
||||
if ($i < 0) {
|
||||
$blockLength += $i;
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
$blockA = \substr($a, $i, $blockLength);
|
||||
$blockB = \substr($b, $i, $blockLength);
|
||||
|
||||
$sum = $blockA - $blockB - $carry;
|
||||
|
||||
if ($sum < 0) {
|
||||
$sum += $complement;
|
||||
$carry = 1;
|
||||
} else {
|
||||
$carry = 0;
|
||||
}
|
||||
|
||||
$sum = (string) $sum;
|
||||
$sumLength = \strlen($sum);
|
||||
|
||||
if ($sumLength < $blockLength) {
|
||||
$sum = \str_repeat('0', $blockLength - $sumLength) . $sum;
|
||||
}
|
||||
|
||||
$result = $sum . $result;
|
||||
|
||||
if ($i === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Carry cannot be 1 when the loop ends, as a > b
|
||||
assert($carry === 0);
|
||||
|
||||
$result = \ltrim($result, '0');
|
||||
|
||||
if ($invert) {
|
||||
$result = $this->neg($result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the multiplication of two non-signed large integers.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function doMul(string $a, string $b) : string
|
||||
{
|
||||
$x = \strlen($a);
|
||||
$y = \strlen($b);
|
||||
|
||||
$maxDigits = \intdiv($this->maxDigits, 2);
|
||||
$complement = 10 ** $maxDigits;
|
||||
|
||||
$result = '0';
|
||||
|
||||
for ($i = $x - $maxDigits;; $i -= $maxDigits) {
|
||||
$blockALength = $maxDigits;
|
||||
|
||||
if ($i < 0) {
|
||||
$blockALength += $i;
|
||||
$i = 0;
|
||||
}
|
||||
|
||||
$blockA = (int) \substr($a, $i, $blockALength);
|
||||
|
||||
$line = '';
|
||||
$carry = 0;
|
||||
|
||||
for ($j = $y - $maxDigits;; $j -= $maxDigits) {
|
||||
$blockBLength = $maxDigits;
|
||||
|
||||
if ($j < 0) {
|
||||
$blockBLength += $j;
|
||||
$j = 0;
|
||||
}
|
||||
|
||||
$blockB = (int) \substr($b, $j, $blockBLength);
|
||||
|
||||
$mul = $blockA * $blockB + $carry;
|
||||
$value = $mul % $complement;
|
||||
$carry = ($mul - $value) / $complement;
|
||||
|
||||
$value = (string) $value;
|
||||
$value = \str_pad($value, $maxDigits, '0', STR_PAD_LEFT);
|
||||
|
||||
$line = $value . $line;
|
||||
|
||||
if ($j === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($carry !== 0) {
|
||||
$line = $carry . $line;
|
||||
}
|
||||
|
||||
$line = \ltrim($line, '0');
|
||||
|
||||
if ($line !== '') {
|
||||
$line .= \str_repeat('0', $x - $blockALength - $i);
|
||||
$result = $this->add($result, $line);
|
||||
}
|
||||
|
||||
if ($i === 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the division of two non-signed large integers.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return string[] The quotient and remainder.
|
||||
*/
|
||||
private function doDiv(string $a, string $b) : array
|
||||
{
|
||||
$cmp = $this->doCmp($a, $b);
|
||||
|
||||
if ($cmp === -1) {
|
||||
return ['0', $a];
|
||||
}
|
||||
|
||||
$x = \strlen($a);
|
||||
$y = \strlen($b);
|
||||
|
||||
// we now know that a >= b && x >= y
|
||||
|
||||
$q = '0'; // quotient
|
||||
$r = $a; // remainder
|
||||
$z = $y; // focus length, always $y or $y+1
|
||||
|
||||
for (;;) {
|
||||
$focus = \substr($a, 0, $z);
|
||||
|
||||
$cmp = $this->doCmp($focus, $b);
|
||||
|
||||
if ($cmp === -1) {
|
||||
if ($z === $x) { // remainder < dividend
|
||||
break;
|
||||
}
|
||||
|
||||
$z++;
|
||||
}
|
||||
|
||||
$zeros = \str_repeat('0', $x - $z);
|
||||
|
||||
$q = $this->add($q, '1' . $zeros);
|
||||
$a = $this->sub($a, $b . $zeros);
|
||||
|
||||
$r = $a;
|
||||
|
||||
if ($r === '0') { // remainder == 0
|
||||
break;
|
||||
}
|
||||
|
||||
$x = \strlen($a);
|
||||
|
||||
if ($x < $y) { // remainder < dividend
|
||||
break;
|
||||
}
|
||||
|
||||
$z = $y;
|
||||
}
|
||||
|
||||
return [$q, $r];
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares two non-signed large numbers.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return int [-1, 0, 1]
|
||||
*/
|
||||
private function doCmp(string $a, string $b) : int
|
||||
{
|
||||
$x = \strlen($a);
|
||||
$y = \strlen($b);
|
||||
|
||||
$cmp = $x <=> $y;
|
||||
|
||||
if ($cmp !== 0) {
|
||||
return $cmp;
|
||||
}
|
||||
|
||||
return \strcmp($a, $b) <=> 0; // enforce [-1, 0, 1]
|
||||
}
|
||||
|
||||
/**
|
||||
* Pads the left of one of the given numbers with zeros if necessary to make both numbers the same length.
|
||||
*
|
||||
* The numbers must only consist of digits, without leading minus sign.
|
||||
*
|
||||
* @param string $a The first operand.
|
||||
* @param string $b The second operand.
|
||||
*
|
||||
* @return array{0: string, 1: string, 2: int}
|
||||
*/
|
||||
private function pad(string $a, string $b) : array
|
||||
{
|
||||
$x = \strlen($a);
|
||||
$y = \strlen($b);
|
||||
|
||||
if ($x > $y) {
|
||||
$b = \str_repeat('0', $x - $y) . $b;
|
||||
|
||||
return [$a, $b, $x];
|
||||
}
|
||||
|
||||
if ($x < $y) {
|
||||
$a = \str_repeat('0', $y - $x) . $a;
|
||||
|
||||
return [$a, $b, $y];
|
||||
}
|
||||
|
||||
return [$a, $b, $x];
|
||||
}
|
||||
}
|
107
admin/phpMyAdmin/vendor/brick/math/src/RoundingMode.php
vendored
Normal file
107
admin/phpMyAdmin/vendor/brick/math/src/RoundingMode.php
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Brick\Math;
|
||||
|
||||
/**
|
||||
* Specifies a rounding behavior for numerical operations capable of discarding precision.
|
||||
*
|
||||
* Each rounding mode indicates how the least significant returned digit of a rounded result
|
||||
* is to be calculated. If fewer digits are returned than the digits needed to represent the
|
||||
* exact numerical result, the discarded digits will be referred to as the discarded fraction
|
||||
* regardless the digits' contribution to the value of the number. In other words, considered
|
||||
* as a numerical value, the discarded fraction could have an absolute value greater than one.
|
||||
*/
|
||||
final class RoundingMode
|
||||
{
|
||||
/**
|
||||
* Private constructor. This class is not instantiable.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the requested operation has an exact result, hence no rounding is necessary.
|
||||
*
|
||||
* If this rounding mode is specified on an operation that yields a result that
|
||||
* cannot be represented at the requested scale, a RoundingNecessaryException is thrown.
|
||||
*/
|
||||
public const UNNECESSARY = 0;
|
||||
|
||||
/**
|
||||
* Rounds away from zero.
|
||||
*
|
||||
* Always increments the digit prior to a nonzero discarded fraction.
|
||||
* Note that this rounding mode never decreases the magnitude of the calculated value.
|
||||
*/
|
||||
public const UP = 1;
|
||||
|
||||
/**
|
||||
* Rounds towards zero.
|
||||
*
|
||||
* Never increments the digit prior to a discarded fraction (i.e., truncates).
|
||||
* Note that this rounding mode never increases the magnitude of the calculated value.
|
||||
*/
|
||||
public const DOWN = 2;
|
||||
|
||||
/**
|
||||
* Rounds towards positive infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for UP; if negative, behaves as for DOWN.
|
||||
* Note that this rounding mode never decreases the calculated value.
|
||||
*/
|
||||
public const CEILING = 3;
|
||||
|
||||
/**
|
||||
* Rounds towards negative infinity.
|
||||
*
|
||||
* If the result is positive, behave as for DOWN; if negative, behave as for UP.
|
||||
* Note that this rounding mode never increases the calculated value.
|
||||
*/
|
||||
public const FLOOR = 4;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.
|
||||
*
|
||||
* Behaves as for UP if the discarded fraction is >= 0.5; otherwise, behaves as for DOWN.
|
||||
* Note that this is the rounding mode commonly taught at school.
|
||||
*/
|
||||
public const HALF_UP = 5;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round down.
|
||||
*
|
||||
* Behaves as for UP if the discarded fraction is > 0.5; otherwise, behaves as for DOWN.
|
||||
*/
|
||||
public const HALF_DOWN = 6;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards positive infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for HALF_UP; if negative, behaves as for HALF_DOWN.
|
||||
*/
|
||||
public const HALF_CEILING = 7;
|
||||
|
||||
/**
|
||||
* Rounds towards "nearest neighbor" unless both neighbors are equidistant, in which case round towards negative infinity.
|
||||
*
|
||||
* If the result is positive, behaves as for HALF_DOWN; if negative, behaves as for HALF_UP.
|
||||
*/
|
||||
public const HALF_FLOOR = 8;
|
||||
|
||||
/**
|
||||
* Rounds towards the "nearest neighbor" unless both neighbors are equidistant, in which case rounds towards the even neighbor.
|
||||
*
|
||||
* Behaves as for HALF_UP if the digit to the left of the discarded fraction is odd;
|
||||
* behaves as for HALF_DOWN if it's even.
|
||||
*
|
||||
* Note that this is the rounding mode that statistically minimizes
|
||||
* cumulative error when applied repeatedly over a sequence of calculations.
|
||||
* It is sometimes known as "Banker's rounding", and is chiefly used in the USA.
|
||||
*/
|
||||
public const HALF_EVEN = 9;
|
||||
}
|
52
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/CHANGELOG.md
vendored
Normal file
52
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased] - yyyy-mm-dd
|
||||
|
||||
## [1.2.1] - 2022-12-03
|
||||
|
||||
- Don't replace `samyoul/u2f-php-server` anymore in `composer.json`
|
||||
- Exclude tests and phpunit config from vendor archives
|
||||
- Apply `wdes/coding-standard` and make constants officially public
|
||||
|
||||
## [1.2.0] - 2021-12-12
|
||||
|
||||
- Added `ReturnTypeWillChange` for PHP 8.1 on SignRequest and RegistrationRequest
|
||||
- Wrote tests for most of the code of this library
|
||||
- Run tests on GitHub actions
|
||||
- Changed the namespace from `Samyoul` to `CodeLts`
|
||||
- Cleaned up the code
|
||||
- Added a `.gitattributes` file
|
||||
- Improved phpdoc blocks
|
||||
- Wrote betters comments
|
||||
- Added a CHANGELOG file
|
||||
- Improved the README file
|
||||
|
||||
## [1.1.4] - 2018-10-26
|
||||
|
||||
- Fix issue when there is more than one U2F key registered
|
||||
|
||||
## [1.1.3] - 2016-12-14
|
||||
|
||||
- Fix public property access bug in `U2FServer` class
|
||||
- Made `SignRequest` class json `JsonSerializable`
|
||||
|
||||
## [1.1.2] - 2016-12-13
|
||||
|
||||
- Replaced `toString()` with `jsonSerialize()` on `RegistrationRequest` class
|
||||
|
||||
## [1.1.1] - 2016-12-13
|
||||
|
||||
- Added `toString()` on `RegistrationRequest` class
|
||||
|
||||
## [1.1.0] - 2016-12-13
|
||||
|
||||
- Re-Namespaced the classes
|
||||
|
||||
## [1.0.0] - 2016-12-12
|
||||
|
||||
- First version
|
26
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/LICENCE
vendored
Normal file
26
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/LICENCE
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
BSD 2-Clause License
|
||||
|
||||
Copyright (c) 2016-2018, Samyoul
|
||||
Copyright (c) 2020, William Desportes
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
452
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/README.md
vendored
Normal file
452
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/README.md
vendored
Normal file
|
@ -0,0 +1,452 @@
|
|||
# U2F-php-server
|
||||
|
||||
[](https://packagist.org/packages/code-lts/u2f-php-server)
|
||||
[](LICENCE)
|
||||
[](https://codecov.io/gh/code-lts/U2F-php-server)
|
||||
|
||||
Server-side handling of FIDO U2F registration and authentication for PHP.
|
||||
|
||||
Securing your online accounts and doing your bit to protect your data is extremely important and increasingly more so as hackers get more sophisticated.
|
||||
FIDO's U2F enables you to add a simple unobtrusive method of 2nd factor authentication, allowing users of your service and/or application to link a hardware key to their account.
|
||||
|
||||
## Story about this library fork
|
||||
|
||||
All started in this [issue](https://github.com/Samyoul/U2F-php-server/issues/8) in October 2020.
|
||||
I quickly worked hard on building tests and opening a [pull-request](https://github.com/Samyoul/U2F-php-server/pull/9).
|
||||
But nothing got merged because the library author vanished.
|
||||
|
||||
### What does change in this fork ?
|
||||
|
||||
For the first released version: nothing changed, only tests where written. And PHP 8.1 support was done.
|
||||
Future versions may change things.
|
||||
|
||||
## The Family of U2F php Libraries
|
||||
|
||||
**Base Library**
|
||||
|
||||
https://github.com/code-lts/U2F-php-server
|
||||
|
||||
## Contents
|
||||
|
||||
1. [Installation](#installation)
|
||||
2. [Requirements](#requirements)
|
||||
1. [OpenSSL](#openssl)
|
||||
1. [Clientside Magic](#client-side-the-magic-javascript-bit-of-talking-with-a-usb-device)
|
||||
1. [HTTPS and SSL](#https-and-ssl)
|
||||
3. [Terminology](#terminology)
|
||||
4. [Recommended Datastore Structure](#recommended-datastore-structure)
|
||||
5. [Process Workflow](#process-workflow)
|
||||
1. [Registration Process Flow](#registration-process-flow)
|
||||
1. [Authentication Process Flow](#authentication-process-flow)
|
||||
6. [Example Code](#example-code)
|
||||
1. [Compatibility Check](#compatibility-code)
|
||||
1. [Registration Code](#registration-code)
|
||||
1. [Authentication Code](#authentication-code)
|
||||
7. [Frameworks](#frameworks)
|
||||
1. [Laravel](#laravel-framework)
|
||||
1. [Yii](#yii-framework)
|
||||
1. [CodeIgniter](#codeigniter-framework)
|
||||
8. [Licence](#licence)
|
||||
9. [Credits](#credits)
|
||||
|
||||
## Installation
|
||||
|
||||
`composer require code-lts/u2f-php-server`
|
||||
|
||||
## Requirements
|
||||
|
||||
A few **things you need** to know before working with this:
|
||||
|
||||
1. [**_OpenSSL_**](#openssl) You need at least OpenSSL 1.0.0 or higher.
|
||||
2. [**_Client-side Handling_**](#client-side) You need to be able to communicate with a some kind of device.
|
||||
3. [**_A HTTPS URL_**](#https-and-ssl) This is very important, without HTTPS U2F simply will not work.
|
||||
4. [**_A Datastore_**](#recommended-datastore-structure) You need some kind of datastore for all your U2F registered users (although if you have a system with user authentication I'm presuming you've got this one sorted).
|
||||
|
||||
### OpenSSL
|
||||
|
||||
This repository requires OpenSSL 1.0.0 or higher. For further details on installing OpenSSL please refer to the [php manual](https://www.php.net/manual/en/openssl.installation.php).
|
||||
|
||||
Also see [Compatibility Code](#compatibility-code), to check if you have the correct version of OpenSSL installed, and are unsure how else to check.
|
||||
|
||||
### Client-side (The magic JavaScript Bit of talking with a USB device)
|
||||
|
||||
My presumption is that if you are looking to add U2F authentication to a php system, then you'll probably are also looking for some client-side handling. You've got a U2F enabled USB device and you want to get the USB device speaking with the browser and then with your server running php.
|
||||
|
||||
1. Google already have this bit sorted : [u2f-api.js](https://github.com/google/u2f-ref-code/blob/master/u2f-gae-demo/war/js/u2f-api.js)
|
||||
2. [Mastahyeti](https://github.com/mastahyeti) has created a repo dedicated to Google's JavaScript Client-side API : https://github.com/mastahyeti/u2f-api
|
||||
|
||||
### HTTPS and SSL
|
||||
|
||||
For U2F to work your website/service must use a HTTPS URL. Without a HTTPS URL your code won't work, so get one for your localhost, get one for your production. https://letsencrypt.org/
|
||||
Basically encrypt everything.
|
||||
|
||||
|
||||
## Terminology
|
||||
|
||||
**_HID_** : _Human Interface Device_, like A USB Device [like these things](https://www.google.co.uk/search?q=fido+usb+key&safe=off&tbm=isch)
|
||||
|
||||
## Recommended Datastore Structure
|
||||
|
||||
You don't need to follow this structure exactly, but you will need to associate your Registration data with a user. You'll also need to store the key handle, public key and the certificate, counter isn't 100% essential but it makes your application more secure.
|
||||
|
||||
|
||||
|Name|Type|Description|
|
||||
|---|---|---|
|
||||
|id|integer primary key||
|
||||
|user_id|integer||
|
||||
|key_handle|varchar(255)||
|
||||
|public_key|varchar(255)||
|
||||
|certificate|text||
|
||||
|counter|integer||
|
||||
|
||||
TODO the descriptions
|
||||
|
||||
## Process Workflow
|
||||
|
||||
### Registration Process Flow
|
||||
|
||||
1. User navigates to a 2nd factor authentication page in your application.
|
||||
|
||||
... TODO add the rest of the registration process flow ...
|
||||
|
||||
### Authentication Process Flow
|
||||
|
||||
1. User navigates to their login page as they usually would, submits username and password.
|
||||
1. Server received POST request authentication data, normal username + password validation occurs
|
||||
1. On successful authentication, the application checks 2nd factor authentication is required. We're going to presume it is, otherwise the user would just be logged in at this stage.
|
||||
1. Application gets the user's registered signatures from the application datastore: `$registrations`.
|
||||
1. Application gets its ID, usually the domain the application is accessible from: `$appId`
|
||||
1. Application makes a `U2F::makeAuthentication($registrations, $appId)` call, the method returns an array of `SignRequest` objects: `$authenticationRequest`.
|
||||
1. Application JSON encodes the array and passes the data to the view
|
||||
1. When the browser loads the page the JavaScript fires the `u2f.sign(authenticationRequest, function(data){ // Callback logic })` function
|
||||
1. The view will use JavaScript / Browser to poll the host machine's ports for a FIDO U2F device
|
||||
1. Once the HID has been found the JavaScript / Browser will send the sign request with data.
|
||||
1. The HID will prompt the user to authorize the sign request
|
||||
1. On success the HID returns authentication data
|
||||
1. The JavaScript receives the HID's returned data and passes it to the server
|
||||
1. The application takes the returned data passes it to the `U2F::authenticate($authenticationRequest, $registrations, $authenticationResponse)` method
|
||||
1. If the method returns a registration and doesn't throw an Exception, authentication is complete.
|
||||
1. Set the user's session, inform the user of the success, and redirect them.
|
||||
|
||||
## Example Code
|
||||
|
||||
For a full working code example for this repository please see [the dedicated example repository](https://github.com/code-lts/U2F-php-server-examples)
|
||||
|
||||
You can also install it with the following:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/code-lts/U2F-php-server-examples.git
|
||||
$ cd u2f-php-server-examples
|
||||
$ composer install
|
||||
```
|
||||
|
||||
|
||||
1. [Compatibility Code](#compatibility-code)
|
||||
2. [Registration Code](#registration-code)
|
||||
1. [Step 1: Starting](#registration-step-1)
|
||||
1. [Step 2: Talking to the HID](#registration-step-2)
|
||||
1. [Step 3: Validation & Storage](#registration-step-3)
|
||||
3. [Authentication Code](#authentication-code)
|
||||
1. [Step 1: Starting](#authentication-step-1)
|
||||
1. [Step 2: Talking to the HID](#authentication-step-2)
|
||||
1. [Step 3: Validation](#authentication-step-3)
|
||||
|
||||
---
|
||||
|
||||
### Compatibility Code
|
||||
|
||||
You'll only ever need to use this method call once per installation and only in the context of debugging if the class is giving you unexpected errors. This method call will check your OpenSSL version and ensure it is at least 1.0.0 .
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use CodeLts\U2F\U2FServer\U2FServer as U2F;
|
||||
|
||||
var_dump(U2F::checkOpenSSLVersion());
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Registration Code
|
||||
|
||||
#### Registration Step 1:
|
||||
**Starting the registration process:**
|
||||
|
||||
We assume that user has successfully authenticated and wishes to register.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
use CodeLts\U2F\U2FServer\U2FServer as U2F;
|
||||
|
||||
session_start();
|
||||
|
||||
// This can be anything, but usually easier if you choose your applications domain and top level domain.
|
||||
$appId = 'yourdomain.tld';
|
||||
|
||||
// Call the makeRegistration method, passing in the app ID
|
||||
$registrationData = U2F::makeRegistration($appId);
|
||||
|
||||
// Store the request for later
|
||||
$_SESSION['registrationRequest'] = $registrationData['request'];
|
||||
|
||||
// Extract the request and signatures, JSON encode them so we can give the data to our javaScript magic
|
||||
$jsRequest = json_encode($registrationData['request']);
|
||||
$jsSignatures = json_encode($registrationData['signatures']);
|
||||
|
||||
// now pass the data to a fictitious view.
|
||||
echo View::make('template/location/u2f-registration.html', [
|
||||
'jsRequest' => $jsRequest,
|
||||
'jsSignatures' => $jsSignatures,
|
||||
]);
|
||||
```
|
||||
|
||||
#### Registration Step 2:
|
||||
**Client-side, Talking To The USB**
|
||||
|
||||
Non-AJAX client-side registration of U2F key token. AJAX can of course be used in your application, but it is easier to demonstrate a linear process without AJAX and callbacks.
|
||||
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<title>U2F Key Registration</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>U2F Registration</h1>
|
||||
<h2>Please enter your FIDO U2F device into your computer's USB port. Then confirm registration on the device.</h2>
|
||||
|
||||
<div style="display:none;">
|
||||
<form id="u2f_submission" method="post" action="auth/u2f-registration/confirm">
|
||||
<input id="u2f_registration_response" name="registration_response" value="" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="javascript" src="https://raw.githubusercontent.com/google/u2f-ref-code/master/u2f-gae-demo/war/js/u2f-api.js"></script>
|
||||
<script>
|
||||
setTimeout(function() {
|
||||
|
||||
// A magic JS function that talks to the USB device. This function will keep polling for the USB device until it finds one.
|
||||
u2f.register([<?php echo $jsRequest ?>], <?php echo $jsSignatures ?>], function(data) {
|
||||
|
||||
// Handle returning error data
|
||||
if(data.errorCode && errorCode != 0) {
|
||||
alert('registration failed with error: ' + data.errorCode);
|
||||
// Or handle the error however you'd like.
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// On success process the data from USB device to send to the server
|
||||
var registration_response = JSON.stringify(data);
|
||||
|
||||
// Get the form items so we can send data back to the server
|
||||
var form = document.getElementById('u2f_submission');
|
||||
var response = document.getElementById('u2f_registration_response');
|
||||
|
||||
// Fill and submit form.
|
||||
response.value = JSON.stringify(registration_response);
|
||||
form.submit();
|
||||
});
|
||||
}, 1000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
#### Registration Step 3:
|
||||
**Validation and Key Storage**
|
||||
|
||||
This is the last stage of registration. Validate the registration response data against the original request data.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require('vendor/autoload.php');
|
||||
use CodeLts\U2F\U2FServer\U2FServer as U2F;
|
||||
|
||||
session_start();
|
||||
|
||||
// Fictitious function representing getting the authenticated user object
|
||||
$user = getAuthenticatedUser();
|
||||
|
||||
try {
|
||||
|
||||
// Validate the registration response against the registration request.
|
||||
// The output are the credentials you need to store for U2F authentication.
|
||||
$validatedRegistration = U2F::register(
|
||||
$_SESSION['registrationRequest'],
|
||||
json_decode($_POST['u2f_registration_response'])
|
||||
);
|
||||
|
||||
// Fictitious function representing the storing of the validated U2F registration data against the authenticated user.
|
||||
$user->storeRegistration($validatedRegistration);
|
||||
|
||||
// Then let your user know what happened
|
||||
$userMessage = 'Success';
|
||||
} catch( Exception $e ) {
|
||||
$userMessage = 'We had an error: '. $e->getMessage();
|
||||
}
|
||||
|
||||
//Fictitious view.
|
||||
echo View::make('template/location/u2f-registration-result.html', [
|
||||
'userMessage' => $userMessage,
|
||||
]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Authentication Code
|
||||
|
||||
#### Authentication Step 1:
|
||||
**Starting the authentication process:**
|
||||
|
||||
We assume that user has successfully authenticated and has previously registered to use FIDO U2F.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require('vendor/autoload.php');
|
||||
use CodeLts\U2F\U2FServer\U2FServer as U2F;
|
||||
|
||||
session_start();
|
||||
|
||||
// Fictitious function representing getting the authenticated user object
|
||||
$user = getAuthenticatedUser();
|
||||
|
||||
// Fictitious function, get U2F registrations associated with the user
|
||||
$registrations = $user->U2FRegistrations();
|
||||
|
||||
// This can be anything, but usually easier if you choose your applications domain and top level domain.
|
||||
$appId = 'yourdomain.tld';
|
||||
|
||||
// Call the U2F makeAuthentication method, passing in the user's registration(s) and the app ID
|
||||
$authenticationRequest = U2F::makeAuthentication($registrations, $appId);
|
||||
|
||||
// Store the request for later
|
||||
$_SESSION['authenticationRequest'] = $authenticationRequest;
|
||||
|
||||
// now pass the data to a fictitious view.
|
||||
echo View::make('template/location/u2f-authentication.html', [
|
||||
'authenticationRequest' => $authenticationRequest,
|
||||
]);
|
||||
```
|
||||
|
||||
#### Authentication Step 2:
|
||||
**Client-side, Talking To The USB**
|
||||
|
||||
Non-AJAX client-side authentication of U2F key token. AJAX can of course be used in your application, but it is easier to demonstrate a linear process without AJAX and callbacks.
|
||||
|
||||
```html
|
||||
<html>
|
||||
<head>
|
||||
<title>U2F Key Authentication</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>U2F Authentication</h1>
|
||||
<h2>Please enter your FIDO U2F device into your computer's USB port. Then confirm authentication on the device.</h2>
|
||||
|
||||
<div style="display:none;">
|
||||
<form id="u2f_submission" method="post" action="auth/u2f-authentication/confirm">
|
||||
<input id="u2f_authentication_response" name="authentication_response" value="" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="javascript" src="https://raw.githubusercontent.com/google/u2f-ref-code/master/u2f-gae-demo/war/js/u2f-api.js"></script>
|
||||
<script>
|
||||
setTimeout(function() {
|
||||
|
||||
// Magic JavaScript talking to your HID
|
||||
u2f.sign(<?php echo $authenticationRequest; ?>, function(data) {
|
||||
|
||||
// Handle returning error data
|
||||
if(data.errorCode && errorCode != 0) {
|
||||
alert('Authentication failed with error: ' + data.errorCode);
|
||||
// Or handle the error however you'd like.
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// On success process the data from USB device to send to the server
|
||||
var authentication_response = JSON.stringify(data);
|
||||
|
||||
// Get the form items so we can send data back to the server
|
||||
var form = document.getElementById('u2f_submission');
|
||||
var response = document.getElementById('u2f_authentication_response');
|
||||
|
||||
// Fill and submit form.
|
||||
response.value = JSON.stringify(authentication_response);
|
||||
form.submit();
|
||||
});
|
||||
}, 1000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
#### Authentication Step 3:
|
||||
**Validation**
|
||||
|
||||
This is the last stage of authentication. Validate the authentication response data against the original request data.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
require('vendor/autoload.php');
|
||||
use CodeLts\U2F\U2FServer\U2FServer as U2F;
|
||||
|
||||
session_start();
|
||||
|
||||
// Fictitious function representing getting the authenticated user object
|
||||
$user = authenticatedUser();
|
||||
|
||||
// Fictitious function, get U2F registrations associated with the user
|
||||
$registrations = $user->U2FRegistrations();
|
||||
|
||||
try {
|
||||
|
||||
// Validate the authentication response against the registration request.
|
||||
// The output are the credentials you need to store for U2F authentication.
|
||||
$validatedAuthentication = U2F::authenticate(
|
||||
$_SESSION['authenticationRequest'],
|
||||
$registrations,
|
||||
json_decode($_POST['u2f_authentication_response'])
|
||||
);
|
||||
|
||||
// Fictitious function representing the updating of the U2F token count integer.
|
||||
$user->updateU2FRegistrationCount($validatedAuthentication);
|
||||
|
||||
// Then let your user know what happened
|
||||
$userMessage = 'Success';
|
||||
} catch( Exception $e ) {
|
||||
$userMessage = 'We had an error: '. $e->getMessage();
|
||||
}
|
||||
|
||||
//Fictitious view.
|
||||
echo View::make('template/location/u2f-authentication-result.html', [
|
||||
'userMessage' => $userMessage,
|
||||
]);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Again, if you want to just download some example code to play with just install the full working code examples written for this repository please see [the dedicated example repository](https://github.com/code-lts/U2F-php-server-examples)
|
||||
|
||||
You can also install it with the following:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/code-lts/U2F-php-server-examples.git
|
||||
$ cd u2f-php-server-examples
|
||||
$ composer install
|
||||
```
|
||||
|
||||
## Licence
|
||||
|
||||
The repository is licensed under a BSD license. [Read details here](https://github.com/code-lts/U2F-php-server/blob/master/LICENCE)
|
||||
|
||||
## Credits
|
||||
|
||||
This repo was originally based on the [Yubico php-u2flib-server](https://github.com/Yubico/php-u2flib-server)
|
50
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/composer.json
vendored
Normal file
50
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/composer.json
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
{
|
||||
"name": "code-lts/u2f-php-server",
|
||||
"description": "Server side handling class for FIDO U2F registration and authentication",
|
||||
"license":"BSD-2-Clause",
|
||||
"homepage": "https://github.com/code-lts/U2F-php-server#readme",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Samuel Hawksby-Robinson",
|
||||
"email": "samuel@samyoul.com"
|
||||
},
|
||||
{
|
||||
"name": "William Desportes",
|
||||
"email": "williamdes@wdes.fr"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/code-lts/U2F-php-server/issues",
|
||||
"source": "https://github.com/code-lts/U2F-php-server"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "@php phpunit",
|
||||
"phpcs": "@php phpcs",
|
||||
"phpcbf": "@php phpcbf"
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0",
|
||||
"ext-openssl":"*"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7 || ^8 || ^9",
|
||||
"wdes/coding-standard": "^3.3"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "CodeLts\\U2F\\U2FServer\\": ["src/"] }
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": { "CodeLts\\U2F\\U2FServer\\Tests\\": ["test/"] }
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true
|
||||
}
|
||||
},
|
||||
"archive": {
|
||||
"exclude": [
|
||||
"/test",
|
||||
"/phpunit.xml"
|
||||
]
|
||||
}
|
||||
}
|
72
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/src/Registration.php
vendored
Normal file
72
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/src/Registration.php
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
<?php
|
||||
|
||||
namespace CodeLts\U2F\U2FServer;
|
||||
|
||||
class Registration
|
||||
{
|
||||
/** The key handle of the registered authenticator */
|
||||
protected $keyHandle;
|
||||
/** The public key of the registered authenticator */
|
||||
protected $publicKey;
|
||||
/** The attestation certificate of the registered authenticator */
|
||||
protected $certificate;
|
||||
/** The counter associated with this registration */
|
||||
protected $counter = -1;
|
||||
|
||||
/**
|
||||
* @param string $keyHandle
|
||||
*/
|
||||
public function setKeyHandle($keyHandle)
|
||||
{
|
||||
$this->keyHandle = $keyHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $publicKey
|
||||
*/
|
||||
public function setPublicKey($publicKey)
|
||||
{
|
||||
$this->publicKey = $publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $certificate
|
||||
*/
|
||||
public function setCertificate($certificate)
|
||||
{
|
||||
$this->certificate = $certificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getKeyHandle()
|
||||
{
|
||||
return $this->keyHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPublicKey()
|
||||
{
|
||||
return $this->publicKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCertificate()
|
||||
{
|
||||
return $this->certificate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCounter()
|
||||
{
|
||||
return $this->counter;
|
||||
}
|
||||
|
||||
}
|
58
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/src/RegistrationRequest.php
vendored
Normal file
58
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/src/RegistrationRequest.php
vendored
Normal file
|
@ -0,0 +1,58 @@
|
|||
<?php
|
||||
|
||||
namespace CodeLts\U2F\U2FServer;
|
||||
|
||||
class RegistrationRequest implements \JsonSerializable
|
||||
{
|
||||
/** @var string Protocol version */
|
||||
protected $version = U2FServer::VERSION;
|
||||
/** @var string Registration challenge */
|
||||
protected $challenge;
|
||||
/** @var string Application id */
|
||||
protected $appId;
|
||||
|
||||
/**
|
||||
* @param string $challenge
|
||||
* @param string $appId
|
||||
*/
|
||||
public function __construct($challenge, $appId)
|
||||
{
|
||||
$this->challenge = $challenge;
|
||||
$this->appId = $appId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function challenge()
|
||||
{
|
||||
return $this->challenge;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function appId()
|
||||
{
|
||||
return $this->appId;
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'version' => $this->version,
|
||||
'challenge' => $this->challenge,
|
||||
'appId' => $this->appId,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
66
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/src/SignRequest.php
vendored
Normal file
66
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/src/SignRequest.php
vendored
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace CodeLts\U2F\U2FServer;
|
||||
|
||||
class SignRequest implements \JsonSerializable
|
||||
{
|
||||
/** @var string Protocol version */
|
||||
protected $version = U2FServer::VERSION;
|
||||
/** @var string Authentication challenge */
|
||||
protected $challenge;
|
||||
/** @var string Key handle of a registered authenticator */
|
||||
protected $keyHandle;
|
||||
/** @var string Application id */
|
||||
protected $appId;
|
||||
|
||||
public function __construct(array $parameters)
|
||||
{
|
||||
$this->challenge = $parameters['challenge'];
|
||||
$this->keyHandle = $parameters['keyHandle'];
|
||||
$this->appId = $parameters['appId'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function version()
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function challenge()
|
||||
{
|
||||
return $this->challenge;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function keyHandle()
|
||||
{
|
||||
return $this->keyHandle;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function appId()
|
||||
{
|
||||
return $this->appId;
|
||||
}
|
||||
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'version' => $this->version,
|
||||
'challenge' => $this->challenge,
|
||||
'keyHandle' => $this->keyHandle,
|
||||
'appId' => $this->appId,
|
||||
];
|
||||
}
|
||||
|
||||
}
|
51
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/src/U2FException.php
vendored
Normal file
51
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/src/U2FException.php
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace CodeLts\U2F\U2FServer;
|
||||
|
||||
class U2FException extends \Exception
|
||||
{
|
||||
/**
|
||||
* Error for the authentication message not matching any outstanding
|
||||
* authentication request
|
||||
*/
|
||||
public const NO_MATCHING_REQUEST = 1;
|
||||
/** Error for the authentication message not matching any registration */
|
||||
public const NO_MATCHING_REGISTRATION = 2;
|
||||
/**
|
||||
* Error for the signature on the authentication message not verifying with
|
||||
* the correct key
|
||||
*/
|
||||
public const AUTHENTICATION_FAILURE = 3;
|
||||
/** Error for the challenge in the registration message not matching the
|
||||
* registration challenge */
|
||||
public const UNMATCHED_CHALLENGE = 4;
|
||||
/**
|
||||
* Error for the attestation signature on the registration message not
|
||||
* verifying
|
||||
*/
|
||||
public const ATTESTATION_SIGNATURE = 5;
|
||||
/** Error for the attestation verification not verifying */
|
||||
public const ATTESTATION_VERIFICATION = 6;
|
||||
/** Error for not getting good random from the system */
|
||||
public const BAD_RANDOM = 7;
|
||||
/** Error when the counter is lower than expected */
|
||||
public const COUNTER_TOO_LOW = 8;
|
||||
/** Error decoding public key */
|
||||
public const PUBKEY_DECODE = 9;
|
||||
/** Error user-agent returned error */
|
||||
public const BAD_UA_RETURNING = 10;
|
||||
/** Error old OpenSSL version */
|
||||
public const OLD_OPENSSL = 11;
|
||||
|
||||
/**
|
||||
* Override constructor and make message and code mandatory
|
||||
* @param string $message
|
||||
* @param int $code
|
||||
* @param \Exception|null $previous
|
||||
*/
|
||||
public function __construct($message, $code, ?\Exception $previous = null)
|
||||
{
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
}
|
440
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/src/U2FServer.php
vendored
Normal file
440
admin/phpMyAdmin/vendor/code-lts/u2f-php-server/src/U2FServer.php
vendored
Normal file
|
@ -0,0 +1,440 @@
|
|||
<?php
|
||||
|
||||
namespace CodeLts\U2F\U2FServer;
|
||||
|
||||
class U2FServer
|
||||
{
|
||||
/** Constant for the version of the u2f protocol */
|
||||
public const VERSION = 'U2F_V2';
|
||||
|
||||
/** @internal */
|
||||
public const PUBKEY_LEN = 65;
|
||||
|
||||
/*
|
||||
* NOTE: If you are lucky and can match this CNs to the hashes please also add it to
|
||||
* the existing test case provider
|
||||
* "CN=Yubico U2F EE Serial 776137165",
|
||||
* "CN=Yubico U2F EE Serial 1086591525",
|
||||
* "CN=Yubico U2F EE Serial 1973679733",
|
||||
* "CN=Yubico U2F EE Serial 13503277888",
|
||||
* "CN=Yubico U2F EE Serial 14803321578"
|
||||
*/
|
||||
|
||||
/**
|
||||
* @internal
|
||||
* @see https://books.google.fr/books?id=SF68CwAAQBAJ&lpg=PT96&ots=PCLmrWyu2F&hl=fr&pg=PT96#v=onepage&q&f=false
|
||||
* @see https://github.com/Yubico/python-u2flib-server/issues/15#issue-107916981
|
||||
*/
|
||||
private static $FIXCERTS = [
|
||||
'349bca1031f8c82c4ceca38b9cebf1a69df9fb3b94eed99eb3fb9aa3822d26e8',
|
||||
'dd574527df608e47ae45fbba75a2afdd5c20fd94a02419381813cd55a2a3398f', // "CN=Yubico U2F EE Serial 13831167861"
|
||||
'1d8764f0f7cd1352df6150045c8f638e517270e8b5dda1c63ade9c2280240cae',
|
||||
'd0edc9a91a1677435a953390865d208c55b3183c6759c9b5a7ff494c322558eb',
|
||||
'6073c436dcd064a48127ddbf6032ac1a66fd59a0c24434f070d4e564c124c897',
|
||||
'ca993121846c464d666096d35f13bf44c1b05af205f9b4a1e00cf6cc10c5e511',
|
||||
];
|
||||
|
||||
/**
|
||||
* @throws U2FException If OpenSSL older than 1.0.0 is used
|
||||
*/
|
||||
public static function checkOpenSSLVersion()
|
||||
{
|
||||
if (OPENSSL_VERSION_NUMBER < 0x10000000) {
|
||||
throw new U2FException(
|
||||
'OpenSSL has to be at least version 1.0.0, this is ' . OPENSSL_VERSION_TEXT,
|
||||
U2FException::OLD_OPENSSL
|
||||
);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to get a registration request to send to a user.
|
||||
* Returns an array of one registration request and a array of sign requests.
|
||||
*
|
||||
* @param string $appId Application id for the running application, Basically the app's URL
|
||||
* @param stdClass[] $registrations List of current registrations for this
|
||||
* user, to prevent the user from registering the same authenticator several
|
||||
* times.
|
||||
* @return array<string,RegistrationRequest|SignRequest[]> An array of two elements, the first containing a
|
||||
* RegisterRequest the second being an array of SignRequest
|
||||
* @throws U2FException
|
||||
*/
|
||||
public static function makeRegistration($appId, array $registrations = [])
|
||||
{
|
||||
$request = new RegistrationRequest(static::createChallenge(), $appId);
|
||||
$signatures = static::makeAuthentication($registrations, $appId);
|
||||
return [
|
||||
'request' => $request,
|
||||
'signatures' => $signatures,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to verify and unpack a registration message.
|
||||
*
|
||||
* @param RegistrationRequest $request this is a reply to
|
||||
* @param object $response response from a user
|
||||
* @param string|null $attestDir The folder to use where trusted CA files are stored (optional)
|
||||
* @param bool $includeCert set to true if the attestation certificate should be
|
||||
* included in the returned Registration object (optional)
|
||||
* @return Registration
|
||||
* @throws U2FException
|
||||
*/
|
||||
public static function register(RegistrationRequest $request, $response, $attestDir = null, $includeCert = true)
|
||||
{
|
||||
// Parameter Checks
|
||||
// $request is safe because of the php typehint
|
||||
|
||||
if (!is_object($response)) {
|
||||
throw new \InvalidArgumentException('$response of register() method only accepts object.');
|
||||
}
|
||||
|
||||
if (property_exists($response, 'errorCode') && $response->errorCode !== 0) {
|
||||
throw new U2FException(
|
||||
'User-agent returned error. Error code: ' . $response->errorCode,
|
||||
U2FException::BAD_UA_RETURNING
|
||||
);
|
||||
}
|
||||
|
||||
if (!is_bool($includeCert)) {
|
||||
throw new \InvalidArgumentException('$include_cert of register() method only accepts boolean.');
|
||||
}
|
||||
|
||||
// Unpack the registration data coming from the client-side token
|
||||
$rawRegistration = static::base64uDecode($response->registrationData);
|
||||
$registrationData = array_values(unpack('C*', $rawRegistration));
|
||||
$clientData = static::base64uDecode($response->clientData);
|
||||
$clientToken = json_decode($clientData);
|
||||
|
||||
// Check Client's challenge matches the original request's challenge
|
||||
if ($clientToken->challenge !== $request->challenge()) {
|
||||
throw new U2FException(
|
||||
'Registration challenge does not match',
|
||||
U2FException::UNMATCHED_CHALLENGE
|
||||
);
|
||||
}
|
||||
|
||||
// Begin validating and building the registration
|
||||
$registration = new Registration();
|
||||
$offset = 1;
|
||||
$pubKey = substr($rawRegistration, $offset, static::PUBKEY_LEN);
|
||||
$offset += static::PUBKEY_LEN;
|
||||
|
||||
// Validate and set the public key
|
||||
if (static::publicKeyToPem($pubKey) === null) {
|
||||
throw new U2FException(
|
||||
'Decoding of public key failed',
|
||||
U2FException::PUBKEY_DECODE
|
||||
);
|
||||
}
|
||||
$registration->setPublicKey(base64_encode($pubKey));
|
||||
|
||||
// Build and set the key handle.
|
||||
$keyHandleLength = $registrationData[$offset++];
|
||||
$keyHandle = substr($rawRegistration, $offset, $keyHandleLength);
|
||||
$offset += $keyHandleLength;
|
||||
$registration->setKeyHandle(static::base64uEncode($keyHandle));
|
||||
|
||||
// Build certificate
|
||||
// Set certificate length
|
||||
// Note: length of certificate is stored in byte 3 and 4 (excluding the first 4 bytes)
|
||||
$certLength = 4;
|
||||
$certLength += ($registrationData[$offset + 2] << 8);
|
||||
$certLength += $registrationData[$offset + 3];
|
||||
|
||||
// Write the certificate from the returning registration data
|
||||
$rawCert = static::fixSignatureUnusedBits(substr($rawRegistration, $offset, $certLength));
|
||||
$offset += $certLength;
|
||||
$pemCert = "-----BEGIN CERTIFICATE-----\r\n";
|
||||
$pemCert .= chunk_split(base64_encode($rawCert), 64);
|
||||
$pemCert .= '-----END CERTIFICATE-----';
|
||||
if ($includeCert) {
|
||||
$registration->setCertificate(base64_encode($rawCert));
|
||||
}
|
||||
|
||||
// If we've set the attestDir, check the given certificate can be used.
|
||||
if ($attestDir) {
|
||||
if (openssl_x509_checkpurpose($pemCert, -1, static::getCerts($attestDir)) !== true) {
|
||||
throw new U2FException(
|
||||
'Attestation certificate can not be validated',
|
||||
U2FException::ATTESTATION_VERIFICATION
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to extract public key from the certificate, if we can't something went wrong in making it.
|
||||
if (!openssl_pkey_get_public($pemCert)) {
|
||||
throw new U2FException(
|
||||
'Decoding of public key failed',
|
||||
U2FException::PUBKEY_DECODE
|
||||
);
|
||||
}
|
||||
|
||||
// Generate signature from the remaining part of the raw registration data
|
||||
$signature = substr($rawRegistration, $offset);
|
||||
|
||||
// Build a verification string from the components we've made in this function
|
||||
$dataToVerify = chr(0);
|
||||
$dataToVerify .= hash('sha256', $request->appId(), true);
|
||||
$dataToVerify .= hash('sha256', $clientData, true);
|
||||
$dataToVerify .= $keyHandle;
|
||||
$dataToVerify .= $pubKey;
|
||||
|
||||
// Verify our data against the signature and the certificate, on success return the registration object
|
||||
if (openssl_verify($dataToVerify, $signature, $pemCert, 'sha256') === 1) {
|
||||
return $registration;
|
||||
} else {
|
||||
throw new U2FException(
|
||||
'Attestation signature does not match',
|
||||
U2FException::ATTESTATION_SIGNATURE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to get an authentication request.
|
||||
*
|
||||
* @param stdClass[] $registrations An array of the registrations to create authentication requests for.
|
||||
* @param string $appId Application id for the running application, Basically the app's URL
|
||||
* @return SignRequest[] An array of SignRequest
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public static function makeAuthentication(array $registrations, $appId)
|
||||
{
|
||||
$signatures = [];
|
||||
$challenge = static::createChallenge();
|
||||
foreach ($registrations as $reg) {
|
||||
if (!is_object($reg)) {
|
||||
throw new \InvalidArgumentException('$registrations of makeAuthentication() method only accepts array of object.');
|
||||
}
|
||||
|
||||
$signatures[] = new SignRequest(
|
||||
[
|
||||
'appId' => $appId,
|
||||
'keyHandle' => $reg->keyHandle,
|
||||
'challenge' => $challenge,
|
||||
]
|
||||
);
|
||||
}
|
||||
return $signatures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to verify an authentication response
|
||||
*
|
||||
* @param SignRequest[] $requests An array of outstanding authentication requests
|
||||
* @param stdClass[] $registrations An array of current registrations
|
||||
* @param object $response A response from the authenticator
|
||||
* @return \stdClass
|
||||
* @throws U2FException
|
||||
*
|
||||
* The Registration object returned on success contains an updated counter
|
||||
* that should be saved for future authentications.
|
||||
* If the Error returned is ERR_COUNTER_TOO_LOW this is an indication of
|
||||
* token cloning or similar and appropriate action should be taken.
|
||||
*/
|
||||
public static function authenticate(array $requests, array $registrations, $response)
|
||||
{
|
||||
// Parameter checks
|
||||
if (!is_object($response)) {
|
||||
throw new \InvalidArgumentException('$response of authenticate() method only accepts object.');
|
||||
}
|
||||
|
||||
if (property_exists($response, 'errorCode') && $response->errorCode !== 0) {
|
||||
throw new U2FException(
|
||||
'User-agent returned error. Error code: ' . $response->errorCode,
|
||||
U2FException::BAD_UA_RETURNING
|
||||
);
|
||||
}
|
||||
|
||||
// Set default values to null, so we get fails by default
|
||||
/** @var object|null $req */
|
||||
$req = null;
|
||||
|
||||
/** @var object|null $reg */
|
||||
$reg = null;
|
||||
|
||||
// Extract client response data
|
||||
$clientData = static::base64uDecode($response->clientData);
|
||||
$decodedClient = json_decode($clientData);
|
||||
|
||||
// Check we have a match among the requests and the response
|
||||
foreach ($requests as $req) {
|
||||
if (!is_object($req)) {
|
||||
throw new \InvalidArgumentException('$requests of authenticate() method only accepts an array of objects.');
|
||||
}
|
||||
|
||||
if ($req->keyHandle() === $response->keyHandle && $req->challenge() === $decodedClient->challenge) {
|
||||
break;
|
||||
}
|
||||
|
||||
$req = null;
|
||||
}
|
||||
if ($req === null) {
|
||||
throw new U2FException(
|
||||
'No matching request found',
|
||||
U2FException::NO_MATCHING_REQUEST
|
||||
);
|
||||
}
|
||||
|
||||
// Check for a match for the response among a list of registrations
|
||||
foreach ($registrations as $reg) {
|
||||
if (!is_object($reg)) {
|
||||
throw new \InvalidArgumentException('$registrations of authenticate() method only accepts an array of objects.');
|
||||
}
|
||||
|
||||
if ($reg->keyHandle === $response->keyHandle) {
|
||||
break;
|
||||
}
|
||||
$reg = null;
|
||||
}
|
||||
if ($reg === null) {
|
||||
throw new U2FException(
|
||||
'No matching registration found',
|
||||
U2FException::NO_MATCHING_REGISTRATION
|
||||
);
|
||||
}
|
||||
|
||||
// On Success, check we have a valid public key
|
||||
$pemKey = static::publicKeyToPem(static::base64uDecode($reg->publicKey));
|
||||
if ($pemKey === null) {
|
||||
throw new U2FException(
|
||||
'Decoding of public key failed',
|
||||
U2FException::PUBKEY_DECODE
|
||||
);
|
||||
}
|
||||
|
||||
// Build signature and data from response
|
||||
$signData = static::base64uDecode($response->signatureData);
|
||||
$dataToVerify = hash('sha256', $req->appId(), true);
|
||||
$dataToVerify .= substr($signData, 0, 5);
|
||||
$dataToVerify .= hash('sha256', $clientData, true);
|
||||
$signature = substr($signData, 5);
|
||||
|
||||
// Verify the response data against the public key
|
||||
if (openssl_verify($dataToVerify, $signature, $pemKey, 'sha256') === 1) {
|
||||
$ctr = unpack('Nctr', substr($signData, 1, 4));
|
||||
$counter = $ctr['ctr'];
|
||||
/* TODO: wrap-around should be handled somehow.. */
|
||||
if ($counter > $reg->counter) {
|
||||
$reg->counter = $counter;
|
||||
return $reg;
|
||||
} else {
|
||||
throw new U2FException(
|
||||
'Counter too low.',
|
||||
U2FException::COUNTER_TOO_LOW
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw new U2FException(
|
||||
'Authentication failed',
|
||||
U2FException::AUTHENTICATION_FAILURE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all files from a directory
|
||||
*
|
||||
* @param string $attestDir The folder to find files into
|
||||
* @return string[]
|
||||
*/
|
||||
private static function getCerts($attestDir)
|
||||
{
|
||||
$files = [];
|
||||
$dir = $attestDir;
|
||||
if ($dir && $handle = opendir($dir)) {
|
||||
while (false !== ($entry = readdir($handle))) {
|
||||
if (is_file($dir . DIRECTORY_SEPARATOR . $entry)) {
|
||||
$files[] = $dir . DIRECTORY_SEPARATOR . $entry;
|
||||
}
|
||||
}
|
||||
closedir($handle);
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @return string
|
||||
*/
|
||||
private static function base64uEncode($data)
|
||||
{
|
||||
return trim(strtr(base64_encode($data), '+/', '-_'), '=');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @return string
|
||||
*/
|
||||
private static function base64uDecode($data)
|
||||
{
|
||||
return base64_decode(strtr($data, '-_', '+/'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @return null|string
|
||||
*/
|
||||
private static function publicKeyToPem($key)
|
||||
{
|
||||
if (strlen($key) !== static::PUBKEY_LEN || $key[0] !== "\x04") {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the public key to binary DER format first
|
||||
* Using the ECC SubjectPublicKeyInfo OIDs from RFC 5480
|
||||
*
|
||||
* SEQUENCE(2 elem) 30 59
|
||||
* SEQUENCE(2 elem) 30 13
|
||||
* OID1.2.840.10045.2.1 (id-ecPublicKey) 06 07 2a 86 48 ce 3d 02 01
|
||||
* OID1.2.840.10045.3.1.7 (secp256r1) 06 08 2a 86 48 ce 3d 03 01 07
|
||||
* BIT STRING(520 bit) 03 42 ..key..
|
||||
*/
|
||||
$der = "\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01";
|
||||
$der .= "\x06\x08\x2a\x86\x48\xce\x3d\x03\x01\x07\x03\x42";
|
||||
$der .= "\0" . $key;
|
||||
|
||||
$pem = "-----BEGIN PUBLIC KEY-----\r\n";
|
||||
$pem .= chunk_split(base64_encode($der), 64);
|
||||
$pem .= '-----END PUBLIC KEY-----';
|
||||
|
||||
return $pem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws U2FException
|
||||
*/
|
||||
private static function createChallenge()
|
||||
{
|
||||
$challenge = openssl_random_pseudo_bytes(32, $crypto_strong);
|
||||
if ($crypto_strong !== true) {
|
||||
throw new U2FException(
|
||||
'Unable to obtain a good source of randomness',
|
||||
U2FException::BAD_RANDOM
|
||||
);
|
||||
}
|
||||
|
||||
$challenge = static::base64uEncode($challenge);
|
||||
|
||||
return $challenge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes a certificate where the signature contains unused bits.
|
||||
*
|
||||
* @param string $cert
|
||||
* @return string
|
||||
*/
|
||||
private static function fixSignatureUnusedBits($cert)
|
||||
{
|
||||
if (in_array(hash('sha256', $cert), static::$FIXCERTS)) {
|
||||
$cert[strlen($cert) - 257] = "\0"; // Fix the "unused bits" field (should always be 0).
|
||||
}
|
||||
return $cert;
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue