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,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 ?? '');
}
}
}