2021-03-01 10:07:03 +01:00
|
|
|
<?php
|
|
|
|
/*
|
|
|
|
* This file is part of the PHPASN1 library.
|
|
|
|
*
|
|
|
|
* Copyright © Friedrich Große <friedrich.grosse@gmail.com>
|
|
|
|
*
|
|
|
|
* For the full copyright and license information, please view the LICENSE
|
|
|
|
* file that was distributed with this source code.
|
|
|
|
*/
|
|
|
|
|
|
|
|
namespace FG\ASN1;
|
|
|
|
|
|
|
|
use ArrayAccess;
|
|
|
|
use ArrayIterator;
|
|
|
|
use Countable;
|
|
|
|
use FG\ASN1\Exception\ParserException;
|
|
|
|
use Iterator;
|
|
|
|
|
|
|
|
abstract class Construct extends ASNObject implements Countable, ArrayAccess, Iterator, Parsable
|
|
|
|
{
|
|
|
|
/** @var \FG\ASN1\ASNObject[] */
|
|
|
|
protected $children;
|
|
|
|
private $iteratorPosition;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param \FG\ASN1\ASNObject[] $children the variadic type hint is commented due to https://github.com/facebook/hhvm/issues/4858
|
|
|
|
*/
|
|
|
|
public function __construct(/* HH_FIXME[4858]: variadic + strict */ ...$children)
|
|
|
|
{
|
|
|
|
$this->children = $children;
|
|
|
|
$this->iteratorPosition = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getContent()
|
|
|
|
{
|
|
|
|
return $this->children;
|
|
|
|
}
|
|
|
|
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public function rewind()
|
|
|
|
{
|
|
|
|
$this->iteratorPosition = 0;
|
|
|
|
}
|
|
|
|
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public function current()
|
|
|
|
{
|
|
|
|
return $this->children[$this->iteratorPosition];
|
|
|
|
}
|
|
|
|
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public function key()
|
|
|
|
{
|
|
|
|
return $this->iteratorPosition;
|
|
|
|
}
|
|
|
|
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public function next()
|
|
|
|
{
|
|
|
|
$this->iteratorPosition++;
|
|
|
|
}
|
|
|
|
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public function valid()
|
|
|
|
{
|
|
|
|
return isset($this->children[$this->iteratorPosition]);
|
|
|
|
}
|
|
|
|
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public function offsetExists($offset)
|
|
|
|
{
|
|
|
|
return array_key_exists($offset, $this->children);
|
|
|
|
}
|
|
|
|
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public function offsetGet($offset)
|
|
|
|
{
|
|
|
|
return $this->children[$offset];
|
|
|
|
}
|
|
|
|
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public function offsetSet($offset, $value)
|
|
|
|
{
|
|
|
|
if ($offset === null) {
|
|
|
|
$offset = count($this->children);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->children[$offset] = $value;
|
|
|
|
}
|
|
|
|
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public function offsetUnset($offset)
|
|
|
|
{
|
|
|
|
unset($this->children[$offset]);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function calculateContentLength()
|
|
|
|
{
|
|
|
|
$length = 0;
|
|
|
|
foreach ($this->children as $component) {
|
|
|
|
$length += $component->getObjectLength();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $length;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function getEncodedValue()
|
|
|
|
{
|
|
|
|
$result = '';
|
|
|
|
foreach ($this->children as $component) {
|
|
|
|
$result .= $component->getBinary();
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addChild(ASNObject $child)
|
|
|
|
{
|
|
|
|
$this->children[] = $child;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function addChildren(array $children)
|
|
|
|
{
|
|
|
|
foreach ($children as $child) {
|
|
|
|
$this->addChild($child);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function __toString()
|
|
|
|
{
|
|
|
|
$nrOfChildren = $this->getNumberOfChildren();
|
|
|
|
$childString = $nrOfChildren == 1 ? 'child' : 'children';
|
|
|
|
|
|
|
|
return "[{$nrOfChildren} {$childString}]";
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getNumberOfChildren()
|
|
|
|
{
|
|
|
|
return count($this->children);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return \FG\ASN1\ASNObject[]
|
|
|
|
*/
|
|
|
|
public function getChildren()
|
|
|
|
{
|
|
|
|
return $this->children;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return \FG\ASN1\ASNObject
|
|
|
|
*/
|
|
|
|
public function getFirstChild()
|
|
|
|
{
|
|
|
|
return $this->children[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $binaryData
|
|
|
|
* @param int $offsetIndex
|
|
|
|
*
|
|
|
|
* @throws Exception\ParserException
|
|
|
|
*
|
|
|
|
* @return Construct|static
|
|
|
|
*/
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public static function fromBinary(&$binaryData, &$offsetIndex = 0)
|
|
|
|
{
|
|
|
|
$parsedObject = new static();
|
|
|
|
self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
|
|
|
|
$contentLength = self::parseContentLength($binaryData, $offsetIndex);
|
|
|
|
$startIndex = $offsetIndex;
|
|
|
|
|
|
|
|
$children = [];
|
|
|
|
$octetsToRead = $contentLength;
|
|
|
|
while ($octetsToRead > 0) {
|
|
|
|
$newChild = ASNObject::fromBinary($binaryData, $offsetIndex);
|
|
|
|
$octetsToRead -= $newChild->getObjectLength();
|
|
|
|
$children[] = $newChild;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($octetsToRead !== 0) {
|
|
|
|
throw new ParserException("Sequence length incorrect", $startIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
$parsedObject->addChildren($children);
|
|
|
|
$parsedObject->setContentLength($contentLength);
|
|
|
|
|
|
|
|
return $parsedObject;
|
|
|
|
}
|
|
|
|
|
2022-02-22 10:27:32 +01:00
|
|
|
#[\ReturnTypeWillChange]
|
2021-03-01 10:07:03 +01:00
|
|
|
public function count($mode = COUNT_NORMAL)
|
|
|
|
{
|
|
|
|
return count($this->children, $mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getIterator()
|
|
|
|
{
|
|
|
|
return new ArrayIterator($this->children);
|
|
|
|
}
|
2022-02-22 10:27:32 +01:00
|
|
|
}
|