Construct.php 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. <?php
  2. /*
  3. * This file is part of the PHPASN1 library.
  4. *
  5. * Copyright © Friedrich Große <friedrich.grosse@gmail.com>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace FG\ASN1;
  11. use ArrayAccess;
  12. use ArrayIterator;
  13. use Countable;
  14. use FG\ASN1\Exception\ParserException;
  15. use Iterator;
  16. abstract class Construct extends ASNObject implements Countable, ArrayAccess, Iterator, Parsable
  17. {
  18. /** @var \FG\ASN1\ASNObject[] */
  19. protected $children;
  20. private $iteratorPosition;
  21. /**
  22. * @param \FG\ASN1\ASNObject[] $children the variadic type hint is commented due to https://github.com/facebook/hhvm/issues/4858
  23. */
  24. public function __construct(/* HH_FIXME[4858]: variadic + strict */ ...$children)
  25. {
  26. $this->children = $children;
  27. $this->iteratorPosition = 0;
  28. }
  29. public function getContent()
  30. {
  31. return $this->children;
  32. }
  33. public function rewind()
  34. {
  35. $this->iteratorPosition = 0;
  36. }
  37. public function current()
  38. {
  39. return $this->children[$this->iteratorPosition];
  40. }
  41. public function key()
  42. {
  43. return $this->iteratorPosition;
  44. }
  45. public function next()
  46. {
  47. $this->iteratorPosition++;
  48. }
  49. public function valid()
  50. {
  51. return isset($this->children[$this->iteratorPosition]);
  52. }
  53. public function offsetExists($offset)
  54. {
  55. return array_key_exists($offset, $this->children);
  56. }
  57. public function offsetGet($offset)
  58. {
  59. return $this->children[$offset];
  60. }
  61. public function offsetSet($offset, $value)
  62. {
  63. if ($offset === null) {
  64. $offset = count($this->children);
  65. }
  66. $this->children[$offset] = $value;
  67. }
  68. public function offsetUnset($offset)
  69. {
  70. unset($this->children[$offset]);
  71. }
  72. protected function calculateContentLength()
  73. {
  74. $length = 0;
  75. foreach ($this->children as $component) {
  76. $length += $component->getObjectLength();
  77. }
  78. return $length;
  79. }
  80. protected function getEncodedValue()
  81. {
  82. $result = '';
  83. foreach ($this->children as $component) {
  84. $result .= $component->getBinary();
  85. }
  86. return $result;
  87. }
  88. public function addChild(ASNObject $child)
  89. {
  90. $this->children[] = $child;
  91. }
  92. public function addChildren(array $children)
  93. {
  94. foreach ($children as $child) {
  95. $this->addChild($child);
  96. }
  97. }
  98. public function __toString()
  99. {
  100. $nrOfChildren = $this->getNumberOfChildren();
  101. $childString = $nrOfChildren == 1 ? 'child' : 'children';
  102. return "[{$nrOfChildren} {$childString}]";
  103. }
  104. public function getNumberOfChildren()
  105. {
  106. return count($this->children);
  107. }
  108. /**
  109. * @return \FG\ASN1\ASNObject[]
  110. */
  111. public function getChildren()
  112. {
  113. return $this->children;
  114. }
  115. /**
  116. * @return \FG\ASN1\ASNObject
  117. */
  118. public function getFirstChild()
  119. {
  120. return $this->children[0];
  121. }
  122. /**
  123. * @param string $binaryData
  124. * @param int $offsetIndex
  125. *
  126. * @throws Exception\ParserException
  127. *
  128. * @return Construct|static
  129. */
  130. public static function fromBinary(&$binaryData, &$offsetIndex = 0)
  131. {
  132. $parsedObject = new static();
  133. self::parseIdentifier($binaryData[$offsetIndex], $parsedObject->getType(), $offsetIndex++);
  134. $contentLength = self::parseContentLength($binaryData, $offsetIndex);
  135. $startIndex = $offsetIndex;
  136. $children = [];
  137. $octetsToRead = $contentLength;
  138. while ($octetsToRead > 0) {
  139. $newChild = ASNObject::fromBinary($binaryData, $offsetIndex);
  140. $octetsToRead -= $newChild->getObjectLength();
  141. $children[] = $newChild;
  142. }
  143. if ($octetsToRead !== 0) {
  144. throw new ParserException("Sequence length incorrect", $startIndex);
  145. }
  146. $parsedObject->addChildren($children);
  147. $parsedObject->setContentLength($contentLength);
  148. return $parsedObject;
  149. }
  150. public function count($mode = COUNT_NORMAL)
  151. {
  152. return count($this->children, $mode);
  153. }
  154. public function getIterator()
  155. {
  156. return new ArrayIterator($this->children);
  157. }
  158. }