installed plugin WP-WebAuthn version 1.2.8

This commit is contained in:
2022-10-08 02:41:03 +00:00
committed by Gitium
parent 15c71c7c0f
commit 7b1024e711
923 changed files with 124568 additions and 0 deletions

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Spomky-Labs
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.

View File

@ -0,0 +1,53 @@
{
"name": "spomky-labs/cbor-php",
"type": "library",
"license": "MIT",
"keywords": ["CBOR", "Concise Binary Object Representation", "RFC7049"],
"description": "CBOR Encoder/Decoder for PHP",
"authors": [
{
"name": "Florent Morselli",
"homepage": "https://github.com/Spomky"
},{
"name": "All contributors",
"homepage": "https://github.com/Spomky-Labs/cbor-php/contributors"
}
],
"autoload": {
"psr-4": {
"CBOR\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"CBOR\\Test\\": "tests/"
}
},
"require": {
"php": ">=7.3",
"brick/math": "^0.8.15|^0.9.0",
"ext-mbstring": "*"
},
"require-dev": {
"ext-json": "*",
"ekino/phpstan-banned-code": "^1.0",
"infection/infection": "^0.18|^0.25",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "^1.0",
"phpstan/phpstan-beberlei-assert": "^1.0",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
"phpstan/phpstan-strict-rules": "^1.0",
"phpunit/phpunit": "^9.5",
"rector/rector": "^0.12",
"roave/security-advisories": "dev-latest",
"symplify/easy-coding-standard": "^10.0"
},
"config": {
"sort-packages": true
},
"suggest": {
"ext-gmp": "GMP or BCMath extensions will drastically improve the library performance",
"ext-bcmath": "GMP or BCMath extensions will drastically improve the library performance. BCMath extension needed to handle the Big Float and Decimal Fraction Tags"
}
}

View File

@ -0,0 +1,50 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use function chr;
abstract class AbstractCBORObject implements CBORObject
{
/**
* @var int
*/
protected $additionalInformation;
/**
* @var int
*/
private $majorType;
public function __construct(int $majorType, int $additionalInformation)
{
$this->majorType = $majorType;
$this->additionalInformation = $additionalInformation;
}
public function __toString(): string
{
return chr($this->majorType << 5 | $this->additionalInformation);
}
public function getMajorType(): int
{
return $this->majorType;
}
public function getAdditionalInformation(): int
{
return $this->additionalInformation;
}
}

View File

@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
final class ByteStringObject extends AbstractCBORObject implements Normalizable
{
private const MAJOR_TYPE = self::MAJOR_TYPE_BYTE_STRING;
/**
* @var string
*/
private $value;
/**
* @var string|null
*/
private $length;
public function __construct(string $data)
{
[$additionalInformation, $length] = LengthCalculator::getLengthOfString($data);
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
$this->length = $length;
$this->value = $data;
}
public function __toString(): string
{
$result = parent::__toString();
if ($this->length !== null) {
$result .= $this->length;
}
return $result . $this->value;
}
public static function create(string $data): self
{
return new self($data);
}
public function getValue(): string
{
return $this->value;
}
public function getLength(): int
{
return mb_strlen($this->value, '8bit');
}
public function normalize(): string
{
return $this->value;
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false): string
{
return $this->value;
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
/**
* @deprecated Will be removed in v3.0. Please use IndefiniteLengthByteStringObject instead
*/
final class ByteStringWithChunkObject extends IndefiniteLengthByteStringObject
{
}

View File

@ -0,0 +1,110 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
interface CBORObject
{
public const MAJOR_TYPE_UNSIGNED_INTEGER = 0b000;
public const MAJOR_TYPE_NEGATIVE_INTEGER = 0b001;
public const MAJOR_TYPE_BYTE_STRING = 0b010;
public const MAJOR_TYPE_TEXT_STRING = 0b011;
public const MAJOR_TYPE_LIST = 0b100;
public const MAJOR_TYPE_MAP = 0b101;
public const MAJOR_TYPE_TAG = 0b110;
public const MAJOR_TYPE_OTHER_TYPE = 0b111;
public const LENGTH_1_BYTE = 0b00011000;
public const LENGTH_2_BYTES = 0b00011001;
public const LENGTH_4_BYTES = 0b00011010;
public const LENGTH_8_BYTES = 0b00011011;
public const LENGTH_INDEFINITE = 0b00011111;
public const FUTURE_USE_1 = 0b00011100;
public const FUTURE_USE_2 = 0b00011101;
public const FUTURE_USE_3 = 0b00011110;
public const OBJECT_FALSE = 20;
public const OBJECT_TRUE = 21;
public const OBJECT_NULL = 22;
public const OBJECT_UNDEFINED = 23;
public const OBJECT_SIMPLE_VALUE = 24;
public const OBJECT_HALF_PRECISION_FLOAT = 25;
public const OBJECT_SINGLE_PRECISION_FLOAT = 26;
public const OBJECT_DOUBLE_PRECISION_FLOAT = 27;
public const OBJECT_BREAK = 0b00011111;
public const TAG_STANDARD_DATETIME = 0;
public const TAG_EPOCH_DATETIME = 1;
public const TAG_UNSIGNED_BIG_NUM = 2;
public const TAG_NEGATIVE_BIG_NUM = 3;
public const TAG_DECIMAL_FRACTION = 4;
public const TAG_BIG_FLOAT = 5;
public const TAG_ENCODED_BASE64_URL = 21;
public const TAG_ENCODED_BASE64 = 22;
public const TAG_ENCODED_BASE16 = 23;
public const TAG_ENCODED_CBOR = 24;
public const TAG_URI = 32;
public const TAG_BASE64_URL = 33;
public const TAG_BASE64 = 34;
public const TAG_MIME = 36;
public const TAG_CBOR = 55799;
public function __toString(): string;
public function getMajorType(): int;
public function getAdditionalInformation(): int;
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*
* @return mixed|null
*/
public function getNormalizedData(bool $ignoreTags = false);
}

View File

@ -0,0 +1,268 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use CBOR\OtherObject\BreakObject;
use CBOR\OtherObject\DoublePrecisionFloatObject;
use CBOR\OtherObject\FalseObject;
use CBOR\OtherObject\HalfPrecisionFloatObject;
use CBOR\OtherObject\NullObject;
use CBOR\OtherObject\OtherObjectManager;
use CBOR\OtherObject\OtherObjectManagerInterface;
use CBOR\OtherObject\SimpleObject;
use CBOR\OtherObject\SinglePrecisionFloatObject;
use CBOR\OtherObject\TrueObject;
use CBOR\OtherObject\UndefinedObject;
use CBOR\Tag\Base16EncodingTag;
use CBOR\Tag\Base64EncodingTag;
use CBOR\Tag\Base64Tag;
use CBOR\Tag\Base64UrlEncodingTag;
use CBOR\Tag\Base64UrlTag;
use CBOR\Tag\BigFloatTag;
use CBOR\Tag\CBOREncodingTag;
use CBOR\Tag\CBORTag;
use CBOR\Tag\DatetimeTag;
use CBOR\Tag\DecimalFractionTag;
use CBOR\Tag\MimeTag;
use CBOR\Tag\NegativeBigIntegerTag;
use CBOR\Tag\TagManager;
use CBOR\Tag\TagManagerInterface;
use CBOR\Tag\TimestampTag;
use CBOR\Tag\UnsignedBigIntegerTag;
use CBOR\Tag\UriTag;
use InvalidArgumentException;
use function ord;
use RuntimeException;
use const STR_PAD_LEFT;
final class Decoder implements DecoderInterface
{
/**
* @var Tag\TagManagerInterface
*/
private $tagManager;
/**
* @var OtherObject\OtherObjectManagerInterface
*/
private $otherObjectManager;
public function __construct(
?TagManagerInterface $tagManager = null,
?OtherObjectManagerInterface $otherTypeManager = null
) {
$this->tagManager = $tagManager ?? $this->generateTagManager();
$this->otherObjectManager = $otherTypeManager ?? $this->generateOtherObjectManager();
}
public static function create(
?TagManagerInterface $tagManager = null,
?OtherObjectManagerInterface $otherObjectManager = null
): self {
return new self($tagManager, $otherObjectManager);
}
public function withTagManager(TagManagerInterface $tagManager): self
{
$this->tagManager = $tagManager;
return $this;
}
public function withOtherObjectManager(OtherObjectManagerInterface $otherObjectManager): self
{
$this->otherObjectManager = $otherObjectManager;
return $this;
}
public function decode(Stream $stream): CBORObject
{
return $this->process($stream, false);
}
private function process(Stream $stream, bool $breakable): CBORObject
{
$ib = ord($stream->read(1));
$mt = $ib >> 5;
$ai = $ib & 0b00011111;
$val = null;
switch ($ai) {
case CBORObject::LENGTH_1_BYTE: //24
case CBORObject::LENGTH_2_BYTES: //25
case CBORObject::LENGTH_4_BYTES: //26
case CBORObject::LENGTH_8_BYTES: //27
$val = $stream->read(2 ** ($ai & 0b00000111));
break;
case CBORObject::FUTURE_USE_1: //28
case CBORObject::FUTURE_USE_2: //29
case CBORObject::FUTURE_USE_3: //30
throw new InvalidArgumentException(sprintf(
'Cannot parse the data. Found invalid Additional Information "%s" (%d).',
str_pad(decbin($ai), 8, '0', STR_PAD_LEFT),
$ai
));
case CBORObject::LENGTH_INDEFINITE: //31
return $this->processInfinite($stream, $mt, $breakable);
}
return $this->processFinite($stream, $mt, $ai, $val);
}
private function processFinite(Stream $stream, int $mt, int $ai, ?string $val): CBORObject
{
switch ($mt) {
case CBORObject::MAJOR_TYPE_UNSIGNED_INTEGER: //0
return UnsignedIntegerObject::createObjectForValue($ai, $val);
case CBORObject::MAJOR_TYPE_NEGATIVE_INTEGER: //1
return NegativeIntegerObject::createObjectForValue($ai, $val);
case CBORObject::MAJOR_TYPE_BYTE_STRING: //2
$length = $val === null ? $ai : Utils::binToInt($val);
return ByteStringObject::create($stream->read($length));
case CBORObject::MAJOR_TYPE_TEXT_STRING: //3
$length = $val === null ? $ai : Utils::binToInt($val);
return TextStringObject::create($stream->read($length));
case CBORObject::MAJOR_TYPE_LIST: //4
$object = ListObject::create();
$nbItems = $val === null ? $ai : Utils::binToInt($val);
for ($i = 0; $i < $nbItems; ++$i) {
$object->add($this->process($stream, false));
}
return $object;
case CBORObject::MAJOR_TYPE_MAP: //5
$object = MapObject::create();
$nbItems = $val === null ? $ai : Utils::binToInt($val);
for ($i = 0; $i < $nbItems; ++$i) {
$object->add($this->process($stream, false), $this->process($stream, false));
}
return $object;
case CBORObject::MAJOR_TYPE_TAG: //6
return $this->tagManager->createObjectForValue($ai, $val, $this->process($stream, false));
case CBORObject::MAJOR_TYPE_OTHER_TYPE: //7
return $this->otherObjectManager->createObjectForValue($ai, $val);
default:
throw new RuntimeException(sprintf(
'Unsupported major type "%s" (%d).',
str_pad(decbin($mt), 5, '0', STR_PAD_LEFT),
$mt
)); // Should never append
}
}
private function processInfinite(Stream $stream, int $mt, bool $breakable): CBORObject
{
switch ($mt) {
case CBORObject::MAJOR_TYPE_BYTE_STRING: //2
$object = IndefiniteLengthByteStringObject::create();
while (! ($it = $this->process($stream, true)) instanceof BreakObject) {
if (! $it instanceof ByteStringObject) {
throw new RuntimeException(
'Unable to parse the data. Infinite Byte String object can only get Byte String objects.'
);
}
$object->add($it);
}
return $object;
case CBORObject::MAJOR_TYPE_TEXT_STRING: //3
$object = IndefiniteLengthTextStringObject::create();
while (! ($it = $this->process($stream, true)) instanceof BreakObject) {
if (! $it instanceof TextStringObject) {
throw new RuntimeException(
'Unable to parse the data. Infinite Text String object can only get Text String objects.'
);
}
$object->add($it);
}
return $object;
case CBORObject::MAJOR_TYPE_LIST: //4
$object = IndefiniteLengthListObject::create();
$it = $this->process($stream, true);
while (! $it instanceof BreakObject) {
$object->add($it);
$it = $this->process($stream, true);
}
return $object;
case CBORObject::MAJOR_TYPE_MAP: //5
$object = IndefiniteLengthMapObject::create();
while (! ($it = $this->process($stream, true)) instanceof BreakObject) {
$object->add($it, $this->process($stream, false));
}
return $object;
case CBORObject::MAJOR_TYPE_OTHER_TYPE: //7
if (! $breakable) {
throw new InvalidArgumentException('Cannot parse the data. No enclosing indefinite.');
}
return BreakObject::create();
case CBORObject::MAJOR_TYPE_UNSIGNED_INTEGER: //0
case CBORObject::MAJOR_TYPE_NEGATIVE_INTEGER: //1
case CBORObject::MAJOR_TYPE_TAG: //6
default:
throw new InvalidArgumentException(sprintf(
'Cannot parse the data. Found infinite length for Major Type "%s" (%d).',
str_pad(decbin($mt), 5, '0', STR_PAD_LEFT),
$mt
));
}
}
private function generateTagManager(): TagManagerInterface
{
return TagManager::create()
->add(DatetimeTag::class)
->add(TimestampTag::class)
->add(UnsignedBigIntegerTag::class)
->add(NegativeBigIntegerTag::class)
->add(DecimalFractionTag::class)
->add(BigFloatTag::class)
->add(Base64UrlEncodingTag::class)
->add(Base64EncodingTag::class)
->add(Base16EncodingTag::class)
->add(CBOREncodingTag::class)
->add(UriTag::class)
->add(Base64UrlTag::class)
->add(Base64Tag::class)
->add(MimeTag::class)
->add(CBORTag::class)
;
}
private function generateOtherObjectManager(): OtherObjectManagerInterface
{
return OtherObjectManager::create()
->add(BreakObject::class)
->add(SimpleObject::class)
->add(FalseObject::class)
->add(TrueObject::class)
->add(NullObject::class)
->add(UndefinedObject::class)
->add(HalfPrecisionFloatObject::class)
->add(SinglePrecisionFloatObject::class)
->add(DoublePrecisionFloatObject::class)
;
}
}

View File

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
interface DecoderInterface
{
public function decode(Stream $stream): CBORObject;
}

View File

@ -0,0 +1,106 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
/**
* @final
*/
class IndefiniteLengthByteStringObject extends AbstractCBORObject implements Normalizable
{
private const MAJOR_TYPE = self::MAJOR_TYPE_BYTE_STRING;
private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
/**
* @var ByteStringObject[]
*/
private $chunks = [];
public function __construct()
{
parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
}
public function __toString(): string
{
$result = parent::__toString();
foreach ($this->chunks as $chunk) {
$result .= $chunk->__toString();
}
return $result . "\xFF";
}
public static function create(): self
{
return new self();
}
public function add(ByteStringObject $chunk): self
{
$this->chunks[] = $chunk;
return $this;
}
public function append(string $chunk): self
{
$this->add(ByteStringObject::create($chunk));
return $this;
}
public function getValue(): string
{
$result = '';
foreach ($this->chunks as $chunk) {
$result .= $chunk->getValue();
}
return $result;
}
public function getLength(): int
{
$length = 0;
foreach ($this->chunks as $chunk) {
$length += $chunk->getLength();
}
return $length;
}
public function normalize(): string
{
$result = '';
foreach ($this->chunks as $chunk) {
$result .= $chunk->normalize();
}
return $result;
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false): string
{
$result = '';
foreach ($this->chunks as $chunk) {
$result .= $chunk->getNormalizedData($ignoreTags);
}
return $result;
}
}

View File

@ -0,0 +1,167 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use function array_key_exists;
use ArrayAccess;
use ArrayIterator;
use function count;
use Countable;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
/**
* @phpstan-implements ArrayAccess<int, CBORObject>
* @phpstan-implements IteratorAggregate<int, CBORObject>
* @final
*/
class IndefiniteLengthListObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess
{
private const MAJOR_TYPE = self::MAJOR_TYPE_LIST;
private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
/**
* @var CBORObject[]
*/
private $data = [];
public function __construct()
{
parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
}
public function __toString(): string
{
$result = parent::__toString();
foreach ($this->data as $object) {
$result .= (string) $object;
}
return $result . "\xFF";
}
public static function create(): self
{
return new self();
}
/**
* @return mixed[]
*/
public function normalize(): array
{
return array_map(static function (CBORObject $object) {
return $object instanceof Normalizable ? $object->normalize() : $object;
}, $this->data);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*
* @return mixed[]
*/
public function getNormalizedData(bool $ignoreTags = false): array
{
return array_map(static function (CBORObject $object) use ($ignoreTags) {
return $object->getNormalizedData($ignoreTags);
}, $this->data);
}
public function add(CBORObject $item): self
{
$this->data[] = $item;
return $this;
}
public function has(int $index): bool
{
return array_key_exists($index, $this->data);
}
public function remove(int $index): self
{
if (! $this->has($index)) {
return $this;
}
unset($this->data[$index]);
$this->data = array_values($this->data);
return $this;
}
public function get(int $index): CBORObject
{
if (! $this->has($index)) {
throw new InvalidArgumentException('Index not found.');
}
return $this->data[$index];
}
public function set(int $index, CBORObject $object): self
{
if (! $this->has($index)) {
throw new InvalidArgumentException('Index not found.');
}
$this->data[$index] = $object;
return $this;
}
/**
* @deprecated The method will be removed on v3.0. No replacement
*/
public function count(): int
{
return count($this->data);
}
/**
* @return Iterator<int, CBORObject>
*/
public function getIterator(): Iterator
{
return new ArrayIterator($this->data);
}
public function offsetExists($offset): bool
{
return $this->has($offset);
}
public function offsetGet($offset): CBORObject
{
return $this->get($offset);
}
public function offsetSet($offset, $value): void
{
if ($offset === null) {
$this->add($value);
return;
}
$this->set($offset, $value);
}
public function offsetUnset($offset): void
{
$this->remove($offset);
}
}

View File

@ -0,0 +1,201 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use function array_key_exists;
use ArrayAccess;
use ArrayIterator;
use function count;
use Countable;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
/**
* @phpstan-implements ArrayAccess<int, CBORObject>
* @phpstan-implements IteratorAggregate<int, MapItem>
* @final
*/
class IndefiniteLengthMapObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess
{
private const MAJOR_TYPE = self::MAJOR_TYPE_MAP;
private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
/**
* @var MapItem[]
*/
private $data = [];
public function __construct()
{
parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
}
public function __toString(): string
{
$result = parent::__toString();
foreach ($this->data as $object) {
$result .= (string) $object->getKey();
$result .= (string) $object->getValue();
}
return $result . "\xFF";
}
public static function create(): self
{
return new self();
}
/**
* @deprecated The method will be removed on v3.0. Please use "add" instead
*/
public function append(CBORObject $key, CBORObject $value): self
{
return $this->add($key, $value);
}
public function add(CBORObject $key, CBORObject $value): self
{
if (! $key instanceof Normalizable) {
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
}
$this->data[$key->normalize()] = MapItem::create($key, $value);
return $this;
}
/**
* @param int|string $key
*/
public function has($key): bool
{
return array_key_exists($key, $this->data);
}
/**
* @param int|string $index
*/
public function remove($index): self
{
if (! $this->has($index)) {
return $this;
}
unset($this->data[$index]);
$this->data = array_values($this->data);
return $this;
}
/**
* @param int|string $index
*/
public function get($index): CBORObject
{
if (! $this->has($index)) {
throw new InvalidArgumentException('Index not found.');
}
return $this->data[$index]->getValue();
}
public function set(MapItem $object): self
{
$key = $object->getKey();
if (! $key instanceof Normalizable) {
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
}
$this->data[$key->normalize()] = $object;
return $this;
}
/**
* @deprecated The method will be removed on v3.0. No replacement
*/
public function count(): int
{
return count($this->data);
}
/**
* @return Iterator<int, MapItem>
*/
public function getIterator(): Iterator
{
return new ArrayIterator($this->data);
}
/**
* @return mixed[]
*/
public function normalize(): array
{
return array_reduce($this->data, static function (array $carry, MapItem $item): array {
$key = $item->getKey();
if (! $key instanceof Normalizable) {
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
}
$valueObject = $item->getValue();
$carry[$key->normalize()] = $valueObject instanceof Normalizable ? $valueObject->normalize() : $valueObject;
return $carry;
}, []);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*
* @return mixed[]
*/
public function getNormalizedData(bool $ignoreTags = false): array
{
return array_reduce($this->data, static function (array $carry, MapItem $item) use ($ignoreTags): array {
$key = $item->getKey();
$valueObject = $item->getValue();
$carry[$key->getNormalizedData($ignoreTags)] = $valueObject->getNormalizedData($ignoreTags);
return $carry;
}, []);
}
public function offsetExists($offset): bool
{
return $this->has($offset);
}
public function offsetGet($offset): CBORObject
{
return $this->get($offset);
}
public function offsetSet($offset, $value): void
{
if (! $offset instanceof CBORObject) {
throw new InvalidArgumentException('Invalid key');
}
if (! $value instanceof CBORObject) {
throw new InvalidArgumentException('Invalid value');
}
$this->set(MapItem::create($offset, $value));
}
public function offsetUnset($offset): void
{
$this->remove($offset);
}
}

View File

@ -0,0 +1,106 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
/**
* @final
*/
class IndefiniteLengthTextStringObject extends AbstractCBORObject implements Normalizable
{
private const MAJOR_TYPE = self::MAJOR_TYPE_TEXT_STRING;
private const ADDITIONAL_INFORMATION = self::LENGTH_INDEFINITE;
/**
* @var TextStringObject[]
*/
private $data = [];
public function __construct()
{
parent::__construct(self::MAJOR_TYPE, self::ADDITIONAL_INFORMATION);
}
public function __toString(): string
{
$result = parent::__toString();
foreach ($this->data as $object) {
$result .= (string) $object;
}
return $result . "\xFF";
}
public static function create(): self
{
return new self();
}
public function add(TextStringObject $chunk): self
{
$this->data[] = $chunk;
return $this;
}
public function append(string $chunk): self
{
$this->add(TextStringObject::create($chunk));
return $this;
}
public function getValue(): string
{
$result = '';
foreach ($this->data as $object) {
$result .= $object->getValue();
}
return $result;
}
public function getLength(): int
{
$length = 0;
foreach ($this->data as $object) {
$length += $object->getLength();
}
return $length;
}
public function normalize(): string
{
$result = '';
foreach ($this->data as $object) {
$result .= $object->normalize();
}
return $result;
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false): string
{
$result = '';
foreach ($this->data as $object) {
$result .= $object->getNormalizedData($ignoreTags);
}
return $result;
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
/**
* @deprecated Will be removed in v3.0. Please use IndefiniteLengthListObject instead
*/
final class InfiniteListObject extends IndefiniteLengthListObject
{
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
/**
* @deprecated Will be removed in v3.0. Please use IndefiniteLengthMapObject instead
*/
final class InfiniteMapObject extends IndefiniteLengthMapObject
{
}

View File

@ -0,0 +1,77 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use Brick\Math\BigInteger;
use function chr;
use function count;
use InvalidArgumentException;
use const STR_PAD_LEFT;
final class LengthCalculator
{
/**
* @return array{int, null|string}
*/
public static function getLengthOfString(string $data): array
{
$length = mb_strlen($data, '8bit');
return self::computeLength($length);
}
/**
* @param array<int|string, mixed> $data
*
* @return array{int, null|string}
*/
public static function getLengthOfArray(array $data): array
{
$length = count($data);
return self::computeLength($length);
}
/**
* @return array{int, null|string}
*/
private static function computeLength(int $length): array
{
switch (true) {
case $length <= 23:
return [$length, null];
case $length <= 0xFF:
return [CBORObject::LENGTH_1_BYTE, chr($length)];
case $length <= 0xFFFF:
return [CBORObject::LENGTH_2_BYTES, self::hex2bin(dechex($length))];
case $length <= 0xFFFFFFFF:
return [CBORObject::LENGTH_4_BYTES, self::hex2bin(dechex($length))];
case BigInteger::of($length)->isLessThanOrEqualTo(BigInteger::fromBase('FFFFFFFFFFFFFFFF', 16)):
return [CBORObject::LENGTH_8_BYTES, self::hex2bin(dechex($length))];
default:
return [CBORObject::LENGTH_INDEFINITE, null];
}
}
private static function hex2bin(string $data): string
{
$data = str_pad($data, (int) (2 ** ceil(log(mb_strlen($data, '8bit'), 2))), '0', STR_PAD_LEFT);
$result = hex2bin($data);
if ($result === false) {
throw new InvalidArgumentException('Unable to convert the data');
}
return $result;
}
}

View File

@ -0,0 +1,187 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use function array_key_exists;
use ArrayAccess;
use ArrayIterator;
use function count;
use Countable;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
/**
* @phpstan-implements ArrayAccess<int, CBORObject>
* @phpstan-implements IteratorAggregate<int, CBORObject>
*/
class ListObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess
{
private const MAJOR_TYPE = self::MAJOR_TYPE_LIST;
/**
* @var CBORObject[]
*/
private $data;
/**
* @var string|null
*/
private $length;
/**
* @param CBORObject[] $data
*/
public function __construct(array $data = [])
{
[$additionalInformation, $length] = LengthCalculator::getLengthOfArray($data);
array_map(static function ($item): void {
if (! $item instanceof CBORObject) {
throw new InvalidArgumentException('The list must contain only CBORObject objects.');
}
}, $data);
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
$this->data = array_values($data);
$this->length = $length;
}
public function __toString(): string
{
$result = parent::__toString();
if ($this->length !== null) {
$result .= $this->length;
}
foreach ($this->data as $object) {
$result .= (string) $object;
}
return $result;
}
/**
* @param CBORObject[] $data
*/
public static function create(array $data = []): self
{
return new self($data);
}
public function add(CBORObject $object): self
{
$this->data[] = $object;
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
return $this;
}
public function has(int $index): bool
{
return array_key_exists($index, $this->data);
}
public function remove(int $index): self
{
if (! $this->has($index)) {
return $this;
}
unset($this->data[$index]);
$this->data = array_values($this->data);
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
return $this;
}
public function get(int $index): CBORObject
{
if (! $this->has($index)) {
throw new InvalidArgumentException('Index not found.');
}
return $this->data[$index];
}
public function set(int $index, CBORObject $object): self
{
if (! $this->has($index)) {
throw new InvalidArgumentException('Index not found.');
}
$this->data[$index] = $object;
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
return $this;
}
/**
* @return array<int, mixed>
*/
public function normalize(): array
{
return array_map(static function (CBORObject $object) {
return $object instanceof Normalizable ? $object->normalize() : $object;
}, $this->data);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*
* @return array<int|string, mixed>
*/
public function getNormalizedData(bool $ignoreTags = false): array
{
return array_map(static function (CBORObject $object) use ($ignoreTags) {
return $object->getNormalizedData($ignoreTags);
}, $this->data);
}
public function count(): int
{
return count($this->data);
}
/**
* @return Iterator<int, CBORObject>
*/
public function getIterator(): Iterator
{
return new ArrayIterator($this->data);
}
public function offsetExists($offset): bool
{
return $this->has($offset);
}
public function offsetGet($offset): CBORObject
{
return $this->get($offset);
}
public function offsetSet($offset, $value): void
{
if ($offset === null) {
$this->add($value);
return;
}
$this->set($offset, $value);
}
public function offsetUnset($offset): void
{
$this->remove($offset);
}
}

View File

@ -0,0 +1,48 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
class MapItem
{
/**
* @var CBORObject
*/
private $key;
/**
* @var CBORObject
*/
private $value;
public function __construct(CBORObject $key, CBORObject $value)
{
$this->key = $key;
$this->value = $value;
}
public static function create(CBORObject $key, CBORObject $value): self
{
return new self($key, $value);
}
public function getKey(): CBORObject
{
return $this->key;
}
public function getValue(): CBORObject
{
return $this->value;
}
}

View File

@ -0,0 +1,217 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use function array_key_exists;
use ArrayAccess;
use ArrayIterator;
use function count;
use Countable;
use InvalidArgumentException;
use Iterator;
use IteratorAggregate;
/**
* @phpstan-implements ArrayAccess<int, CBORObject>
* @phpstan-implements IteratorAggregate<int, MapItem>
*/
final class MapObject extends AbstractCBORObject implements Countable, IteratorAggregate, Normalizable, ArrayAccess
{
private const MAJOR_TYPE = self::MAJOR_TYPE_MAP;
/**
* @var MapItem[]
*/
private $data;
/**
* @var string|null
*/
private $length;
/**
* @param MapItem[] $data
*/
public function __construct(array $data = [])
{
[$additionalInformation, $length] = LengthCalculator::getLengthOfArray($data);
array_map(static function ($item): void {
if (! $item instanceof MapItem) {
throw new InvalidArgumentException('The list must contain only MapItem objects.');
}
}, $data);
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
$this->data = $data;
$this->length = $length;
}
public function __toString(): string
{
$result = parent::__toString();
if ($this->length !== null) {
$result .= $this->length;
}
foreach ($this->data as $object) {
$result .= $object->getKey()
->__toString()
;
$result .= $object->getValue()
->__toString()
;
}
return $result;
}
/**
* @param MapItem[] $data
*/
public static function create(array $data = []): self
{
return new self($data);
}
public function add(CBORObject $key, CBORObject $value): self
{
if (! $key instanceof Normalizable) {
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
}
$this->data[$key->normalize()] = MapItem::create($key, $value);
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
return $this;
}
/**
* @param int|string $key
*/
public function has($key): bool
{
return array_key_exists($key, $this->data);
}
/**
* @param int|string $index
*/
public function remove($index): self
{
if (! $this->has($index)) {
return $this;
}
unset($this->data[$index]);
$this->data = array_values($this->data);
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
return $this;
}
/**
* @param int|string $index
*/
public function get($index): CBORObject
{
if (! $this->has($index)) {
throw new InvalidArgumentException('Index not found.');
}
return $this->data[$index]->getValue();
}
public function set(MapItem $object): self
{
$key = $object->getKey();
if (! $key instanceof Normalizable) {
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
}
$this->data[$key->normalize()] = $object;
[$this->additionalInformation, $this->length] = LengthCalculator::getLengthOfArray($this->data);
return $this;
}
public function count(): int
{
return count($this->data);
}
/**
* @return Iterator<int, MapItem>
*/
public function getIterator(): Iterator
{
return new ArrayIterator($this->data);
}
/**
* @return array<int|string, mixed>
*/
public function normalize(): array
{
return array_reduce($this->data, static function (array $carry, MapItem $item): array {
$key = $item->getKey();
if (! $key instanceof Normalizable) {
throw new InvalidArgumentException('Invalid key. Shall be normalizable');
}
$valueObject = $item->getValue();
$carry[$key->normalize()] = $valueObject instanceof Normalizable ? $valueObject->normalize() : $valueObject;
return $carry;
}, []);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*
* @return array<int|string, mixed>
*/
public function getNormalizedData(bool $ignoreTags = false): array
{
return array_reduce($this->data, static function (array $carry, MapItem $item) use ($ignoreTags): array {
$key = $item->getKey();
$valueObject = $item->getValue();
$carry[$key->getNormalizedData($ignoreTags)] = $valueObject->getNormalizedData($ignoreTags);
return $carry;
}, []);
}
public function offsetExists($offset): bool
{
return $this->has($offset);
}
public function offsetGet($offset): CBORObject
{
return $this->get($offset);
}
public function offsetSet($offset, $value): void
{
if (! $offset instanceof CBORObject) {
throw new InvalidArgumentException('Invalid key');
}
if (! $value instanceof CBORObject) {
throw new InvalidArgumentException('Invalid value');
}
$this->set(MapItem::create($offset, $value));
}
public function offsetUnset($offset): void
{
$this->remove($offset);
}
}

View File

@ -0,0 +1,136 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use Brick\Math\BigInteger;
use InvalidArgumentException;
use const STR_PAD_LEFT;
/**
* @final
*/
class NegativeIntegerObject extends AbstractCBORObject implements Normalizable
{
private const MAJOR_TYPE = self::MAJOR_TYPE_NEGATIVE_INTEGER;
/**
* @var string|null
*/
private $data;
public function __construct(int $additionalInformation, ?string $data)
{
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
$this->data = $data;
}
public function __toString(): string
{
$result = parent::__toString();
if ($this->data !== null) {
$result .= $this->data;
}
return $result;
}
public static function createObjectForValue(int $additionalInformation, ?string $data): self
{
return new self($additionalInformation, $data);
}
public static function create(int $value): self
{
return self::createFromString((string) $value);
}
public static function createFromString(string $value): self
{
$integer = BigInteger::of($value);
return self::createBigInteger($integer);
}
public function getValue(): string
{
if ($this->data === null) {
return (string) (-1 - $this->additionalInformation);
}
$result = Utils::binToBigInteger($this->data);
$minusOne = BigInteger::of(-1);
return $minusOne->minus($result)
->toBase(10)
;
}
public function normalize(): string
{
return $this->getValue();
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false): string
{
return $this->getValue();
}
private static function createBigInteger(BigInteger $integer): self
{
if ($integer->isGreaterThanOrEqualTo(BigInteger::zero())) {
throw new InvalidArgumentException('The value must be a negative integer.');
}
$minusOne = BigInteger::of(-1);
$computed_value = $minusOne->minus($integer);
switch (true) {
case $computed_value->isLessThan(BigInteger::of(24)):
$ai = $computed_value->toInt();
$data = null;
break;
case $computed_value->isLessThan(BigInteger::fromBase('FF', 16)):
$ai = 24;
$data = self::hex2bin(str_pad($computed_value->toBase(16), 2, '0', STR_PAD_LEFT));
break;
case $computed_value->isLessThan(BigInteger::fromBase('FFFF', 16)):
$ai = 25;
$data = self::hex2bin(str_pad($computed_value->toBase(16), 4, '0', STR_PAD_LEFT));
break;
case $computed_value->isLessThan(BigInteger::fromBase('FFFFFFFF', 16)):
$ai = 26;
$data = self::hex2bin(str_pad($computed_value->toBase(16), 8, '0', STR_PAD_LEFT));
break;
default:
throw new InvalidArgumentException(
'Out of range. Please use NegativeBigIntegerTag tag with ByteStringObject object instead.'
);
}
return new self($ai, $data);
}
private static function hex2bin(string $data): string
{
$result = hex2bin($data);
if ($result === false) {
throw new InvalidArgumentException('Unable to convert the data');
}
return $result;
}
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
interface Normalizable
{
/**
* @return mixed|null
*/
public function normalize();
}

View File

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
abstract class OtherObject extends AbstractCBORObject
{
private const MAJOR_TYPE = self::MAJOR_TYPE_OTHER_TYPE;
/**
* @var string|null
*/
protected $data;
public function __construct(int $additionalInformation, ?string $data)
{
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
$this->data = $data;
}
public function __toString(): string
{
$result = parent::__toString();
if ($this->data !== null) {
$result .= $this->data;
}
return $result;
}
public function getContent(): ?string
{
return $this->data;
}
/**
* @return int[]
*/
abstract public static function supportedAdditionalInformation(): array;
abstract public static function createFromLoadedData(int $additionalInformation, ?string $data): self;
}

View File

@ -0,0 +1,47 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use CBOR\OtherObject as Base;
final class BreakObject extends Base
{
public function __construct()
{
parent::__construct(self::OBJECT_BREAK, null);
}
public static function create(): self
{
return new self();
}
public static function supportedAdditionalInformation(): array
{
return [self::OBJECT_BREAK];
}
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
{
return new self();
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false): bool
{
return false;
}
}

View File

@ -0,0 +1,97 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use Brick\Math\BigInteger;
use CBOR\Normalizable;
use CBOR\OtherObject as Base;
use CBOR\Utils;
use const INF;
use InvalidArgumentException;
use const NAN;
final class DoublePrecisionFloatObject extends Base implements Normalizable
{
public static function supportedAdditionalInformation(): array
{
return [self::OBJECT_DOUBLE_PRECISION_FLOAT];
}
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
{
return new self($additionalInformation, $data);
}
public static function create(string $value): self
{
if (mb_strlen($value, '8bit') !== 8) {
throw new InvalidArgumentException('The value is not a valid double precision floating point');
}
return new self(self::OBJECT_DOUBLE_PRECISION_FLOAT, $value);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->normalize();
}
/**
* @return float|int
*/
public function normalize()
{
$exponent = $this->getExponent();
$mantissa = $this->getMantissa();
$sign = $this->getSign();
if ($exponent === 0) {
$val = $mantissa * 2 ** (-(1022 + 52));
} elseif ($exponent !== 0b11111111111) {
$val = ($mantissa + (1 << 52)) * 2 ** ($exponent - (1023 + 52));
} else {
$val = $mantissa === 0 ? INF : NAN;
}
return $sign * $val;
}
public function getExponent(): int
{
$data = $this->data;
Utils::assertString($data, 'Invalid data');
return Utils::binToBigInteger($data)->shiftedRight(52)->and(Utils::hexToBigInteger('7ff'))->toInt();
}
public function getMantissa(): int
{
$data = $this->data;
Utils::assertString($data, 'Invalid data');
return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('fffffffffffff'))->toInt();
}
public function getSign(): int
{
$data = $this->data;
Utils::assertString($data, 'Invalid data');
$sign = Utils::binToBigInteger($data)->shiftedRight(63);
return $sign->isEqualTo(BigInteger::one()) ? -1 : 1;
}
}

View File

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use CBOR\Normalizable;
use CBOR\OtherObject as Base;
final class FalseObject extends Base implements Normalizable
{
public function __construct()
{
parent::__construct(self::OBJECT_FALSE, null);
}
public static function create(): self
{
return new self();
}
public static function supportedAdditionalInformation(): array
{
return [self::OBJECT_FALSE];
}
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
{
return new self();
}
public function normalize(): bool
{
return false;
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false): bool
{
return $this->normalize();
}
}

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use CBOR\OtherObject as Base;
use InvalidArgumentException;
use function ord;
final class GenericObject extends Base
{
public static function supportedAdditionalInformation(): array
{
return [];
}
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
{
if ($data !== null && ord($data) < 32) {
throw new InvalidArgumentException('Invalid simple value. Content data should not be present.');
}
return new self($additionalInformation, $data);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->data;
}
}

View File

@ -0,0 +1,97 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use Brick\Math\BigInteger;
use CBOR\Normalizable;
use CBOR\OtherObject as Base;
use CBOR\Utils;
use const INF;
use InvalidArgumentException;
use const NAN;
final class HalfPrecisionFloatObject extends Base implements Normalizable
{
public static function supportedAdditionalInformation(): array
{
return [self::OBJECT_HALF_PRECISION_FLOAT];
}
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
{
return new self($additionalInformation, $data);
}
public static function create(string $value): self
{
if (mb_strlen($value, '8bit') !== 2) {
throw new InvalidArgumentException('The value is not a valid half precision floating point');
}
return new self(self::OBJECT_HALF_PRECISION_FLOAT, $value);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->normalize();
}
/**
* @return float|int
*/
public function normalize()
{
$exponent = $this->getExponent();
$mantissa = $this->getMantissa();
$sign = $this->getSign();
if ($exponent === 0) {
$val = $mantissa * 2 ** (-24);
} elseif ($exponent !== 0b11111) {
$val = ($mantissa + (1 << 10)) * 2 ** ($exponent - 25);
} else {
$val = $mantissa === 0 ? INF : NAN;
}
return $sign * $val;
}
public function getExponent(): int
{
$data = $this->data;
Utils::assertString($data, 'Invalid data');
return Utils::binToBigInteger($data)->shiftedRight(10)->and(Utils::hexToBigInteger('1f'))->toInt();
}
public function getMantissa(): int
{
$data = $this->data;
Utils::assertString($data, 'Invalid data');
return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('3ff'))->toInt();
}
public function getSign(): int
{
$data = $this->data;
Utils::assertString($data, 'Invalid data');
$sign = Utils::binToBigInteger($data)->shiftedRight(15);
return $sign->isEqualTo(BigInteger::one()) ? -1 : 1;
}
}

View File

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use CBOR\Normalizable;
use CBOR\OtherObject as Base;
final class NullObject extends Base implements Normalizable
{
public function __construct()
{
parent::__construct(self::OBJECT_NULL, null);
}
public static function create(): self
{
return new self();
}
public static function supportedAdditionalInformation(): array
{
return [self::OBJECT_NULL];
}
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
{
return new self();
}
public function normalize(): ?string
{
return null;
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->normalize();
}
}

View File

@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use function array_key_exists;
use CBOR\OtherObject;
use InvalidArgumentException;
/**
* @final
*/
class OtherObjectManager implements OtherObjectManagerInterface
{
/**
* @var string[]
*/
private $classes = [];
public static function create(): self
{
return new self();
}
public function add(string $class): self
{
foreach ($class::supportedAdditionalInformation() as $ai) {
if ($ai < 0) {
throw new InvalidArgumentException('Invalid additional information.');
}
$this->classes[$ai] = $class;
}
return $this;
}
public function getClassForValue(int $value): string
{
return array_key_exists($value, $this->classes) ? $this->classes[$value] : GenericObject::class;
}
public function createObjectForValue(int $value, ?string $data): OtherObject
{
/** @var OtherObject $class */
$class = $this->getClassForValue($value);
return $class::createFromLoadedData($value, $data);
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use CBOR\OtherObject;
interface OtherObjectManagerInterface
{
public function createObjectForValue(int $value, ?string $data): OtherObject;
}

View File

@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use CBOR\Normalizable;
use CBOR\OtherObject as Base;
use CBOR\Utils;
use function chr;
use InvalidArgumentException;
use function ord;
final class SimpleObject extends Base implements Normalizable
{
public static function supportedAdditionalInformation(): array
{
return array_merge(range(0, 19), [24]);
}
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
{
if ($additionalInformation === 24) {
if ($data === null) {
throw new InvalidArgumentException('Invalid simple value. Content data is missing.');
}
if (mb_strlen($data, '8bit') !== 1) {
throw new InvalidArgumentException('Invalid simple value. Content data is too long.');
}
if (ord($data) < 32) {
throw new InvalidArgumentException('Invalid simple value. Content data must be between 32 and 255.');
}
} elseif ($additionalInformation < 20) {
if ($data !== null) {
throw new InvalidArgumentException('Invalid simple value. Content data should not be present.');
}
}
return new self($additionalInformation, $data);
}
public function normalize(): int
{
if ($this->data === null) {
return $this->getAdditionalInformation();
}
return Utils::binToInt($this->data);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false): int
{
return $this->normalize();
}
public static function create(int $value): self
{
switch (true) {
case $value < 32:
return new self($value, null);
case $value < 256:
return new self(24, chr($value));
default:
throw new InvalidArgumentException('The value is not a valid simple value.');
}
}
}

View File

@ -0,0 +1,96 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use Brick\Math\BigInteger;
use CBOR\OtherObject as Base;
use CBOR\Utils;
use const INF;
use InvalidArgumentException;
use const NAN;
final class SinglePrecisionFloatObject extends Base
{
public static function supportedAdditionalInformation(): array
{
return [self::OBJECT_SINGLE_PRECISION_FLOAT];
}
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
{
return new self($additionalInformation, $data);
}
public static function create(string $value): self
{
if (mb_strlen($value, '8bit') !== 4) {
throw new InvalidArgumentException('The value is not a valid single precision floating point');
}
return new self(self::OBJECT_SINGLE_PRECISION_FLOAT, $value);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->normalize();
}
/**
* @return float|int
*/
public function normalize()
{
$exponent = $this->getExponent();
$mantissa = $this->getMantissa();
$sign = $this->getSign();
if ($exponent === 0) {
$val = $mantissa * 2 ** (-(126 + 23));
} elseif ($exponent !== 0b11111111) {
$val = ($mantissa + (1 << 23)) * 2 ** ($exponent - (127 + 23));
} else {
$val = $mantissa === 0 ? INF : NAN;
}
return $sign * $val;
}
public function getExponent(): int
{
$data = $this->data;
Utils::assertString($data, 'Invalid data');
return Utils::binToBigInteger($data)->shiftedRight(23)->and(Utils::hexToBigInteger('ff'))->toInt();
}
public function getMantissa(): int
{
$data = $this->data;
Utils::assertString($data, 'Invalid data');
return Utils::binToBigInteger($data)->and(Utils::hexToBigInteger('7fffff'))->toInt();
}
public function getSign(): int
{
$data = $this->data;
Utils::assertString($data, 'Invalid data');
$sign = Utils::binToBigInteger($data)->shiftedRight(31);
return $sign->isEqualTo(BigInteger::one()) ? -1 : 1;
}
}

View File

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use CBOR\Normalizable;
use CBOR\OtherObject as Base;
final class TrueObject extends Base implements Normalizable
{
public function __construct()
{
parent::__construct(self::OBJECT_TRUE, null);
}
public static function create(): self
{
return new self();
}
public static function supportedAdditionalInformation(): array
{
return [self::OBJECT_TRUE];
}
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
{
return new self();
}
public function normalize(): bool
{
return true;
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false): bool
{
return $this->normalize();
}
}

View File

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\OtherObject;
use CBOR\OtherObject as Base;
final class UndefinedObject extends Base
{
public function __construct()
{
parent::__construct(self::OBJECT_UNDEFINED, null);
}
public static function create(): self
{
return new self();
}
public static function supportedAdditionalInformation(): array
{
return [self::OBJECT_UNDEFINED];
}
public static function createFromLoadedData(int $additionalInformation, ?string $data): Base
{
return new self();
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*
* @return string
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return 'undefined';
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
/**
* @deprecated Will be removed in v3.0. Please use NegativeIntegerObject instead
*/
final class SignedIntegerObject extends NegativeIntegerObject
{
}

View File

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
interface Stream
{
public function read(int $length): string;
}

View File

@ -0,0 +1,85 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use InvalidArgumentException;
use RuntimeException;
final class StringStream implements Stream
{
/**
* @var resource
*/
private $resource;
public function __construct(string $data)
{
$resource = fopen('php://memory', 'rb+');
if ($resource === false) {
throw new RuntimeException('Unable to open the memory');
}
$result = fwrite($resource, $data);
if ($result === false) {
throw new RuntimeException('Unable to write the memory');
}
$result = rewind($resource);
if ($result === false) {
throw new RuntimeException('Unable to rewind the memory');
}
$this->resource = $resource;
}
public static function create(string $data): self
{
return new self($data);
}
public function read(int $length): string
{
if ($length === 0) {
return '';
}
$alreadyRead = 0;
$data = '';
while ($alreadyRead < $length) {
$left = $length - $alreadyRead;
$sizeToRead = $left < 1024 && $left > 0 ? $left : 1024;
$newData = fread($this->resource, $sizeToRead);
$alreadyRead += $sizeToRead;
if ($newData === false) {
throw new RuntimeException('Unable to read the memory');
}
if (mb_strlen($newData, '8bit') < $sizeToRead) {
throw new InvalidArgumentException(sprintf(
'Out of range. Expected: %d, read: %d.',
$length,
mb_strlen($data, '8bit')
));
}
$data .= $newData;
}
if (mb_strlen($data, '8bit') !== $length) {
throw new InvalidArgumentException(sprintf(
'Out of range. Expected: %d, read: %d.',
$length,
mb_strlen($data, '8bit')
));
}
return $data;
}
}

View File

@ -0,0 +1,99 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use InvalidArgumentException;
abstract class Tag extends AbstractCBORObject
{
private const MAJOR_TYPE = self::MAJOR_TYPE_TAG;
/**
* @var string|null
*/
protected $data;
/**
* @var CBORObject
*/
protected $object;
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
$this->data = $data;
$this->object = $object;
}
public function __toString(): string
{
$result = parent::__toString();
if ($this->data !== null) {
$result .= $this->data;
}
return $result . $this->object;
}
public function getData(): ?string
{
return $this->data;
}
abstract public static function getTagId(): int;
abstract public static function createFromLoadedData(
int $additionalInformation,
?string $data,
CBORObject $object
): self;
public function getValue(): CBORObject
{
return $this->object;
}
/**
* @return array{int, null|string}
*/
protected static function determineComponents(int $tag): array
{
switch (true) {
case $tag < 0:
throw new InvalidArgumentException('The value must be a positive integer.');
case $tag < 24:
return [$tag, null];
case $tag < 0xFF:
return [24, self::hex2bin(dechex($tag))];
case $tag < 0xFFFF:
return [25, self::hex2bin(dechex($tag))];
case $tag < 0xFFFFFFFF:
return [26, self::hex2bin(dechex($tag))];
default:
throw new InvalidArgumentException(
'Out of range. Please use PositiveBigIntegerTag tag with ByteStringObject object instead.'
);
}
}
private static function hex2bin(string $data): string
{
$result = hex2bin($data);
if ($result === false) {
throw new InvalidArgumentException('Unable to convert the data');
}
return $result;
}
}

View File

@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\ByteStringObject;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthByteStringObject;
use CBOR\IndefiniteLengthTextStringObject;
use CBOR\Tag;
use CBOR\TextStringObject;
final class Base16EncodingTag extends Tag
{
public static function getTagId(): int
{
return self::TAG_ENCODED_BASE16;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_ENCODED_BASE16);
return new self($ai, $data, $object);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
if ($ignoreTags) {
return $this->object->getNormalizedData($ignoreTags);
}
if (! $this->object instanceof ByteStringObject && ! $this->object instanceof IndefiniteLengthByteStringObject && ! $this->object instanceof TextStringObject && ! $this->object instanceof IndefiniteLengthTextStringObject) {
return $this->object->getNormalizedData($ignoreTags);
}
return bin2hex($this->object->getNormalizedData($ignoreTags));
}
}

View File

@ -0,0 +1,63 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\ByteStringObject;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthByteStringObject;
use CBOR\IndefiniteLengthTextStringObject;
use CBOR\Tag;
use CBOR\TextStringObject;
use InvalidArgumentException;
final class Base64EncodingTag extends Tag
{
public static function getTagId(): int
{
return self::TAG_ENCODED_BASE64;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_ENCODED_BASE64);
return new self($ai, $data, $object);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
if ($ignoreTags) {
return $this->object->getNormalizedData($ignoreTags);
}
if (! $this->object instanceof ByteStringObject && ! $this->object instanceof IndefiniteLengthByteStringObject && ! $this->object instanceof TextStringObject && ! $this->object instanceof IndefiniteLengthTextStringObject) {
return $this->object->getNormalizedData($ignoreTags);
}
$result = base64_decode($this->object->getNormalizedData($ignoreTags), true);
if ($result === false) {
throw new InvalidArgumentException('Unable to decode the data');
}
return $result;
}
}

View File

@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthTextStringObject;
use CBOR\Tag;
use CBOR\TextStringObject;
use InvalidArgumentException;
final class Base64Tag extends Tag
{
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
if (! $object instanceof TextStringObject && ! $object instanceof IndefiniteLengthTextStringObject) {
throw new InvalidArgumentException('This tag only accepts a Text String object.');
}
parent::__construct($additionalInformation, $data, $object);
}
public static function getTagId(): int
{
return self::TAG_BASE64;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_BASE64);
return new self($ai, $data, $object);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->object->getNormalizedData($ignoreTags);
}
}

View File

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\ByteStringObject;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthByteStringObject;
use CBOR\IndefiniteLengthTextStringObject;
use CBOR\Tag;
use CBOR\TextStringObject;
use CBOR\Utils;
final class Base64UrlEncodingTag extends Tag
{
public static function getTagId(): int
{
return self::TAG_ENCODED_BASE64_URL;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_ENCODED_BASE64_URL);
return new self($ai, $data, $object);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
if ($ignoreTags) {
return $this->object->getNormalizedData($ignoreTags);
}
if (! $this->object instanceof ByteStringObject && ! $this->object instanceof IndefiniteLengthByteStringObject && ! $this->object instanceof TextStringObject && ! $this->object instanceof IndefiniteLengthTextStringObject) {
return $this->object->getNormalizedData($ignoreTags);
}
return Utils::decode($this->object->getNormalizedData($ignoreTags));
}
}

View File

@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthTextStringObject;
use CBOR\Tag;
use CBOR\TextStringObject;
use InvalidArgumentException;
final class Base64UrlTag extends Tag
{
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
if (! $object instanceof TextStringObject && ! $object instanceof IndefiniteLengthTextStringObject) {
throw new InvalidArgumentException('This tag only accepts a Text String object.');
}
parent::__construct($additionalInformation, $data, $object);
}
public static function getTagId(): int
{
return self::TAG_BASE64_URL;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_BASE64_URL);
return new self($ai, $data, $object);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->object->getNormalizedData($ignoreTags);
}
}

View File

@ -0,0 +1,108 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\ListObject;
use CBOR\NegativeIntegerObject;
use CBOR\Normalizable;
use CBOR\Tag;
use CBOR\UnsignedIntegerObject;
use function count;
use function extension_loaded;
use InvalidArgumentException;
use RuntimeException;
final class BigFloatTag extends Tag implements Normalizable
{
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
if (! extension_loaded('bcmath')) {
throw new RuntimeException('The extension "bcmath" is required to use this tag');
}
if (! $object instanceof ListObject || count($object) !== 2) {
throw new InvalidArgumentException(
'This tag only accepts a ListObject object that contains an exponent and a mantissa.'
);
}
$e = $object->get(0);
if (! $e instanceof UnsignedIntegerObject && ! $e instanceof NegativeIntegerObject) {
throw new InvalidArgumentException('The exponent must be a Signed Integer or an Unsigned Integer object.');
}
$m = $object->get(1);
if (! $m instanceof UnsignedIntegerObject && ! $m instanceof NegativeIntegerObject && ! $m instanceof NegativeBigIntegerTag && ! $m instanceof UnsignedBigIntegerTag) {
throw new InvalidArgumentException(
'The mantissa must be a Positive or Negative Signed Integer or an Unsigned Integer object.'
);
}
parent::__construct($additionalInformation, $data, $object);
}
public static function getTagId(): int
{
return self::TAG_BIG_FLOAT;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_BIG_FLOAT);
return new self($ai, $data, $object);
}
public static function createFromExponentAndMantissa(CBORObject $e, CBORObject $m): Tag
{
$object = ListObject::create()
->add($e)
->add($m)
;
return self::create($object);
}
public function normalize()
{
/** @var ListObject $object */
$object = $this->object;
/** @var UnsignedIntegerObject|NegativeIntegerObject $e */
$e = $object->get(0);
/** @var UnsignedIntegerObject|NegativeIntegerObject|NegativeBigIntegerTag|UnsignedBigIntegerTag $m */
$m = $object->get(1);
return rtrim(bcmul($m->normalize(), bcpow('2', $e->normalize(), 100), 100), '0');
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
if ($ignoreTags) {
return $this->object->getNormalizedData($ignoreTags);
}
if (! $this->object instanceof ListObject || count($this->object) !== 2) {
return $this->object->getNormalizedData($ignoreTags);
}
return $this->normalize();
}
}

View File

@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\ByteStringObject;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthByteStringObject;
use CBOR\Tag;
use InvalidArgumentException;
final class CBOREncodingTag extends Tag
{
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
if (! $object instanceof ByteStringObject && ! $object instanceof IndefiniteLengthByteStringObject) {
throw new InvalidArgumentException('This tag only accepts a Byte String object.');
}
parent::__construct($additionalInformation, $data, $object);
}
public static function getTagId(): int
{
return self::TAG_ENCODED_CBOR;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_ENCODED_CBOR);
return new self($ai, $data, $object);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->object->getNormalizedData($ignoreTags);
}
}

View File

@ -0,0 +1,54 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\Normalizable;
use CBOR\Tag;
final class CBORTag extends Tag implements Normalizable
{
public static function getTagId(): int
{
return self::TAG_CBOR;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_CBOR);
return new self($ai, $data, $object);
}
/**
* @return mixed|CBORObject|null
*/
public function normalize()
{
return $this->object instanceof Normalizable ? $this->object->normalize() : $this->object;
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->object->getNormalizedData($ignoreTags);
}
}

View File

@ -0,0 +1,84 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthTextStringObject;
use CBOR\Normalizable;
use CBOR\Tag;
use CBOR\TextStringObject;
use const DATE_RFC3339;
use DateTimeImmutable;
use DateTimeInterface;
use InvalidArgumentException;
/**
* @final
*/
class DatetimeTag extends Tag implements Normalizable
{
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
if (! $object instanceof TextStringObject && ! $object instanceof IndefiniteLengthTextStringObject) {
throw new InvalidArgumentException('This tag only accepts a Byte String object.');
}
parent::__construct($additionalInformation, $data, $object);
}
public static function getTagId(): int
{
return self::TAG_STANDARD_DATETIME;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_STANDARD_DATETIME);
return new self($ai, $data, $object);
}
public function normalize(): DateTimeInterface
{
/** @var TextStringObject|IndefiniteLengthTextStringObject $object */
$object = $this->object;
$result = DateTimeImmutable::createFromFormat(DATE_RFC3339, $object->normalize());
if ($result !== false) {
return $result;
}
$formatted = DateTimeImmutable::createFromFormat('Y-m-d\TH:i:s.uP', $object->normalize());
if ($formatted === false) {
throw new InvalidArgumentException('Invalid data. Cannot be converted into a datetime object');
}
return $formatted;
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
if ($ignoreTags) {
return $this->object->getNormalizedData($ignoreTags);
}
return $this->normalize();
}
}

View File

@ -0,0 +1,114 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\ListObject;
use CBOR\NegativeIntegerObject;
use CBOR\Normalizable;
use CBOR\Tag;
use CBOR\UnsignedIntegerObject;
use function count;
use function extension_loaded;
use InvalidArgumentException;
use RuntimeException;
final class DecimalFractionTag extends Tag implements Normalizable
{
public function __construct(CBORObject $object)
{
if (! extension_loaded('bcmath')) {
throw new RuntimeException('The extension "bcmath" is required to use this tag');
}
if (! $object instanceof ListObject || count($object) !== 2) {
throw new InvalidArgumentException(
'This tag only accepts a ListObject object that contains an exponent and a mantissa.'
);
}
$e = $object->get(0);
if (! $e instanceof UnsignedIntegerObject && ! $e instanceof NegativeIntegerObject) {
throw new InvalidArgumentException('The exponent must be a Signed Integer or an Unsigned Integer object.');
}
$m = $object->get(1);
if (! $m instanceof UnsignedIntegerObject && ! $m instanceof NegativeIntegerObject && ! $m instanceof NegativeBigIntegerTag && ! $m instanceof UnsignedBigIntegerTag) {
throw new InvalidArgumentException(
'The mantissa must be a Positive or Negative Signed Integer or an Unsigned Integer object.'
);
}
parent::__construct(self::TAG_DECIMAL_FRACTION, null, $object);
}
public static function create(CBORObject $object): self
{
return new self($object);
}
public static function getTagId(): int
{
return self::TAG_DECIMAL_FRACTION;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($object);
}
public static function createFromExponentAndMantissa(CBORObject $e, CBORObject $m): Tag
{
$object = ListObject::create()
->add($e)
->add($m)
;
return self::create($object);
}
public function normalize()
{
/** @var ListObject $object */
$object = $this->object;
/** @var UnsignedIntegerObject|NegativeIntegerObject $e */
$e = $object->get(0);
/** @var UnsignedIntegerObject|NegativeIntegerObject|NegativeBigIntegerTag|UnsignedBigIntegerTag $m */
$m = $object->get(1);
return rtrim(bcmul($m->normalize(), bcpow('10', $e->normalize(), 100), 100), '0');
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
if ($ignoreTags) {
return $this->object->getNormalizedData($ignoreTags);
}
if (! $this->object instanceof ListObject || count($this->object) !== 2) {
return $this->object->getNormalizedData($ignoreTags);
}
$e = $this->object->get(0);
$m = $this->object->get(1);
if (! $e instanceof UnsignedIntegerObject && ! $e instanceof NegativeIntegerObject) {
return $this->object->getNormalizedData($ignoreTags);
}
if (! $m instanceof UnsignedIntegerObject && ! $m instanceof NegativeIntegerObject && ! $m instanceof NegativeBigIntegerTag && ! $m instanceof UnsignedBigIntegerTag) {
return $this->object->getNormalizedData($ignoreTags);
}
return $this->normalize();
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
/**
* @deprecated The class EpochTag is deprecated and will be removed in v3.0. Please use DatetimeTag instead
*/
final class EpochTag extends DatetimeTag
{
}

View File

@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\Tag;
final class GenericTag extends Tag
{
public static function getTagId(): int
{
return -1;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->object;
}
}

View File

@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthTextStringObject;
use CBOR\Normalizable;
use CBOR\Tag;
use CBOR\TextStringObject;
use InvalidArgumentException;
final class MimeTag extends Tag implements Normalizable
{
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
if (! $object instanceof TextStringObject && ! $object instanceof IndefiniteLengthTextStringObject) {
throw new InvalidArgumentException('This tag only accepts a Byte String object.');
}
parent::__construct($additionalInformation, $data, $object);
}
public static function getTagId(): int
{
return self::TAG_MIME;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_MIME);
return new self($ai, $data, $object);
}
public function normalize(): string
{
/** @var TextStringObject|IndefiniteLengthTextStringObject $object */
$object = $this->object;
return $object->normalize();
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->object->getNormalizedData($ignoreTags);
}
}

View File

@ -0,0 +1,83 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use Brick\Math\BigInteger;
use CBOR\ByteStringObject;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthByteStringObject;
use CBOR\Normalizable;
use CBOR\Tag;
use InvalidArgumentException;
final class NegativeBigIntegerTag extends Tag implements Normalizable
{
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
if (! $object instanceof ByteStringObject && ! $object instanceof IndefiniteLengthByteStringObject) {
throw new InvalidArgumentException('This tag only accepts a Byte String object.');
}
parent::__construct($additionalInformation, $data, $object);
}
public static function getTagId(): int
{
return self::TAG_NEGATIVE_BIG_NUM;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_NEGATIVE_BIG_NUM);
return new self($ai, $data, $object);
}
public function normalize(): string
{
/** @var ByteStringObject|IndefiniteLengthByteStringObject $object */
$object = $this->object;
$integer = BigInteger::fromBase(bin2hex($object->getValue()), 16);
$minusOne = BigInteger::of(-1);
return $minusOne->minus($integer)
->toBase(10)
;
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
if ($ignoreTags) {
return $this->object->getNormalizedData($ignoreTags);
}
if (! $this->object instanceof ByteStringObject) {
return $this->object->getNormalizedData($ignoreTags);
}
$integer = BigInteger::fromBase(bin2hex($this->object->getValue()), 16);
$minusOne = BigInteger::of(-1);
return $minusOne->minus($integer)
->toBase(10)
;
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
/**
* @deprecated Will be removed in v3.0. Please use UnsignedBigIntegerTag instead
*/
final class PositiveBigIntegerTag extends UnsignedBigIntegerTag
{
}

View File

@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use function array_key_exists;
use CBOR\CBORObject;
use CBOR\Tag;
use CBOR\Utils;
use InvalidArgumentException;
/**
* @final
*/
class TagManager implements TagManagerInterface
{
/**
* @var string[]
*/
private $classes = [];
public static function create(): self
{
return new self();
}
public function add(string $class): self
{
if ($class::getTagId() < 0) {
throw new InvalidArgumentException('Invalid tag ID.');
}
$this->classes[$class::getTagId()] = $class;
return $this;
}
public function getClassForValue(int $value): string
{
return array_key_exists($value, $this->classes) ? $this->classes[$value] : GenericTag::class;
}
public function createObjectForValue(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
$value = $additionalInformation;
if ($additionalInformation >= 24) {
Utils::assertString($data, 'Invalid data');
$value = Utils::binToInt($data);
}
/** @var Tag $class */
$class = $this->getClassForValue($value);
return $class::createFromLoadedData($additionalInformation, $data, $object);
}
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\Tag;
interface TagManagerInterface
{
public function createObjectForValue(int $additionalInformation, ?string $data, CBORObject $object): Tag;
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
/**
* @deprecated Will be removed in v3.0. Please use TagManager instead
*/
class TagObjectManager extends TagManager
{
}

View File

@ -0,0 +1,111 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\NegativeIntegerObject;
use CBOR\Normalizable;
use CBOR\OtherObject\DoublePrecisionFloatObject;
use CBOR\OtherObject\HalfPrecisionFloatObject;
use CBOR\OtherObject\SinglePrecisionFloatObject;
use CBOR\Tag;
use CBOR\UnsignedIntegerObject;
use DateTimeImmutable;
use DateTimeInterface;
use InvalidArgumentException;
use const STR_PAD_RIGHT;
final class TimestampTag extends Tag implements Normalizable
{
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
if (! $object instanceof UnsignedIntegerObject && ! $object instanceof NegativeIntegerObject && ! $object instanceof HalfPrecisionFloatObject && ! $object instanceof SinglePrecisionFloatObject && ! $object instanceof DoublePrecisionFloatObject) {
throw new InvalidArgumentException('This tag only accepts integer-based or float-based objects.');
}
parent::__construct($additionalInformation, $data, $object);
}
public static function getTagId(): int
{
return self::TAG_EPOCH_DATETIME;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_EPOCH_DATETIME);
return new self($ai, $data, $object);
}
public function normalize(): DateTimeInterface
{
$object = $this->object;
switch (true) {
case $object instanceof UnsignedIntegerObject:
case $object instanceof NegativeIntegerObject:
$formatted = DateTimeImmutable::createFromFormat('U', $object->normalize());
break;
case $object instanceof HalfPrecisionFloatObject:
case $object instanceof SinglePrecisionFloatObject:
case $object instanceof DoublePrecisionFloatObject:
$value = (string) $object->normalize();
$parts = explode('.', $value);
if (isset($parts[1])) {
if (mb_strlen($parts[1], '8bit') > 6) {
$parts[1] = mb_substr($parts[1], 0, 6, '8bit');
} else {
$parts[1] = str_pad($parts[1], 6, '0', STR_PAD_RIGHT);
}
}
$formatted = DateTimeImmutable::createFromFormat('U.u', implode('.', $parts));
break;
default:
throw new InvalidArgumentException('Unable to normalize the object');
}
if ($formatted === false) {
throw new InvalidArgumentException('Invalid data. Cannot be converted into a datetime object');
}
return $formatted;
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
if ($ignoreTags) {
return $this->object->getNormalizedData($ignoreTags);
}
switch (true) {
case $this->object instanceof UnsignedIntegerObject:
case $this->object instanceof NegativeIntegerObject:
case $this->object instanceof HalfPrecisionFloatObject:
case $this->object instanceof SinglePrecisionFloatObject:
case $this->object instanceof DoublePrecisionFloatObject:
return $this->normalize();
default:
return $this->object->getNormalizedData($ignoreTags);
}
}
}

View File

@ -0,0 +1,78 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\ByteStringObject;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthByteStringObject;
use CBOR\Normalizable;
use CBOR\Tag;
use CBOR\Utils;
use InvalidArgumentException;
/**
* @final
*/
class UnsignedBigIntegerTag extends Tag implements Normalizable
{
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
if (! $object instanceof ByteStringObject && ! $object instanceof IndefiniteLengthByteStringObject) {
throw new InvalidArgumentException('This tag only accepts a Byte String object.');
}
parent::__construct($additionalInformation, $data, $object);
}
public static function getTagId(): int
{
return self::TAG_UNSIGNED_BIG_NUM;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_UNSIGNED_BIG_NUM);
return new self($ai, $data, $object);
}
public function normalize(): string
{
/** @var ByteStringObject|IndefiniteLengthByteStringObject $object */
$object = $this->object;
return Utils::hexToString($object->normalize());
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
if ($ignoreTags) {
return $this->object->getNormalizedData($ignoreTags);
}
if (! $this->object instanceof ByteStringObject) {
return $this->object->getNormalizedData($ignoreTags);
}
return Utils::hexToString($this->object->getValue());
}
}

View File

@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR\Tag;
use CBOR\CBORObject;
use CBOR\IndefiniteLengthTextStringObject;
use CBOR\Normalizable;
use CBOR\Tag;
use CBOR\TextStringObject;
use InvalidArgumentException;
final class UriTag extends Tag implements Normalizable
{
public function __construct(int $additionalInformation, ?string $data, CBORObject $object)
{
if (! $object instanceof TextStringObject && ! $object instanceof IndefiniteLengthTextStringObject) {
throw new InvalidArgumentException('This tag only accepts a Text String object.');
}
parent::__construct($additionalInformation, $data, $object);
}
public static function getTagId(): int
{
return self::TAG_URI;
}
public static function createFromLoadedData(int $additionalInformation, ?string $data, CBORObject $object): Tag
{
return new self($additionalInformation, $data, $object);
}
public static function create(CBORObject $object): Tag
{
[$ai, $data] = self::determineComponents(self::TAG_URI);
return new self($ai, $data, $object);
}
public function normalize(): string
{
/** @var TextStringObject|IndefiniteLengthTextStringObject $object */
$object = $this->object;
return $object->normalize();
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false)
{
return $this->object->getNormalizedData($ignoreTags);
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
/**
* @deprecated Will be removed in v3.0. Please use Tag instead
*/
abstract class TagObject extends Tag
{
}

View File

@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
final class TextStringObject extends AbstractCBORObject implements Normalizable
{
private const MAJOR_TYPE = self::MAJOR_TYPE_TEXT_STRING;
/**
* @var string|null
*/
private $length;
/**
* @var string
*/
private $data;
public function __construct(string $data)
{
[$additionalInformation, $length] = LengthCalculator::getLengthOfString($data);
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
$this->data = $data;
$this->length = $length;
}
public function __toString(): string
{
$result = parent::__toString();
if ($this->length !== null) {
$result .= $this->length;
}
return $result . $this->data;
}
public static function create(string $data): self
{
return new self($data);
}
public function getValue(): string
{
return $this->data;
}
public function getLength(): int
{
return mb_strlen($this->data, 'utf8');
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false): string
{
return $this->data;
}
public function normalize()
{
return $this->data;
}
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
/**
* @deprecated Will be removed in v3.0. Please use IndefiniteLengthTextStringObject instead
*/
final class TextStringWithChunkObject extends IndefiniteLengthTextStringObject
{
}

View File

@ -0,0 +1,139 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use Brick\Math\BigInteger;
use InvalidArgumentException;
use const STR_PAD_LEFT;
final class UnsignedIntegerObject extends AbstractCBORObject implements Normalizable
{
private const MAJOR_TYPE = self::MAJOR_TYPE_UNSIGNED_INTEGER;
/**
* @var string|null
*/
private $data;
public function __construct(int $additionalInformation, ?string $data)
{
parent::__construct(self::MAJOR_TYPE, $additionalInformation);
$this->data = $data;
}
public function __toString(): string
{
$result = parent::__toString();
if ($this->data !== null) {
$result .= $this->data;
}
return $result;
}
public static function createObjectForValue(int $additionalInformation, ?string $data): self
{
return new self($additionalInformation, $data);
}
public static function create(int $value): self
{
return self::createFromString((string) $value);
}
public static function createFromHex(string $value): self
{
$integer = BigInteger::fromBase($value, 16);
return self::createBigInteger($integer);
}
public static function createFromString(string $value): self
{
$integer = BigInteger::of($value);
return self::createBigInteger($integer);
}
public function getMajorType(): int
{
return self::MAJOR_TYPE;
}
public function getValue(): string
{
if ($this->data === null) {
return (string) $this->additionalInformation;
}
$integer = BigInteger::fromBase(bin2hex($this->data), 16);
return $integer->toBase(10);
}
public function normalize(): string
{
return $this->getValue();
}
/**
* @deprecated The method will be removed on v3.0. Please rely on the CBOR\Normalizable interface
*/
public function getNormalizedData(bool $ignoreTags = false): string
{
return $this->getValue();
}
private static function createBigInteger(BigInteger $integer): self
{
if ($integer->isLessThan(BigInteger::zero())) {
throw new InvalidArgumentException('The value must be a positive integer.');
}
switch (true) {
case $integer->isLessThan(BigInteger::of(24)):
$ai = $integer->toInt();
$data = null;
break;
case $integer->isLessThan(BigInteger::fromBase('FF', 16)):
$ai = 24;
$data = self::hex2bin(str_pad($integer->toBase(16), 2, '0', STR_PAD_LEFT));
break;
case $integer->isLessThan(BigInteger::fromBase('FFFF', 16)):
$ai = 25;
$data = self::hex2bin(str_pad($integer->toBase(16), 4, '0', STR_PAD_LEFT));
break;
case $integer->isLessThan(BigInteger::fromBase('FFFFFFFF', 16)):
$ai = 26;
$data = self::hex2bin(str_pad($integer->toBase(16), 8, '0', STR_PAD_LEFT));
break;
default:
throw new InvalidArgumentException(
'Out of range. Please use PositiveBigIntegerTag tag with ByteStringObject object instead.'
);
}
return new self($ai, $data);
}
private static function hex2bin(string $data): string
{
$result = hex2bin($data);
if ($result === false) {
throw new InvalidArgumentException('Unable to convert the data');
}
return $result;
}
}

View File

@ -0,0 +1,69 @@
<?php
declare(strict_types=1);
/*
* The MIT License (MIT)
*
* Copyright (c) 2018-2020 Spomky-Labs
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace CBOR;
use Brick\Math\BigInteger;
use InvalidArgumentException;
use function is_string;
/**
* @internal
*/
abstract class Utils
{
public static function binToInt(string $value): int
{
return self::binToBigInteger($value)->toInt();
}
public static function binToBigInteger(string $value): BigInteger
{
return self::hexToBigInteger(bin2hex($value));
}
public static function hexToInt(string $value): int
{
return self::hexToBigInteger($value)->toInt();
}
public static function hexToBigInteger(string $value): BigInteger
{
return BigInteger::fromBase($value, 16);
}
public static function hexToString(string $value): string
{
return BigInteger::fromBase(bin2hex($value), 16)->toBase(10);
}
public static function decode(string $data): string
{
$decoded = base64_decode(strtr($data, '-_', '+/'), true);
if ($decoded === false) {
throw new InvalidArgumentException('Invalid data provided');
}
return $decoded;
}
/**
* @param mixed|null $data
*/
public static function assertString($data, ?string $message = null): void
{
if (! is_string($data)) {
throw new InvalidArgumentException($message ?? '');
}
}
}