Seditio Source
Root |
./othercms/xenForo 2.2.8/src/vendor/fgrosse/phpasn1/lib/ASN1/ExplicitlyTaggedObject.php
<?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
FG\ASN1\Exception\ParserException;

/**
 * Class ExplicitlyTaggedObject decorate an inner object with an additional tag that gives information about
 * its context specific meaning.
 *
 * Explanation taken from A Layman's Guide to a Subset of ASN.1, BER, and DER:
 * >>> An RSA Laboratories Technical Note
 * >>> Burton S. Kaliski Jr.
 * >>> Revised November 1, 1993
 *
 * [...]
 * Explicitly tagged types are derived from other types by adding an outer tag to the underlying type.
 * In effect, explicitly tagged types are structured types consisting of one component, the underlying type.
 * Explicit tagging is denoted by the ASN.1 keywords [class number] EXPLICIT (see Section 5.2).
 * [...]
 *
 * @see http://luca.ntop.org/Teaching/Appunti/asn1.html
 */
class ExplicitlyTaggedObject extends ASNObject
{
   
/** @var \FG\ASN1\ASNObject[] */
   
private $decoratedObjects;
    private
$tag;

   
/**
     * @param int $tag
     * @param \FG\ASN1\ASNObject $objects,...
     */
   
public function __construct($tag, /* HH_FIXME[4858]: variadic + strict */ ...$objects)
    {
       
$this->tag = $tag;
       
$this->decoratedObjects = $objects;
    }

    protected function
calculateContentLength()
    {
       
$length = 0;
        foreach (
$this->decoratedObjects as $object) {
           
$length += $object->getObjectLength();
        }

        return
$length;
    }

    protected function
getEncodedValue()
    {
       
$encoded = '';
        foreach (
$this->decoratedObjects as $object) {
           
$encoded .= $object->getBinary();
        }

        return
$encoded;
    }

    public function
getContent()
    {
        return
$this->decoratedObjects;
    }

    public function
__toString()
    {
        switch (
$length = count($this->decoratedObjects)) {
        case
0:
            return
"Context specific empty object with tag [{$this->tag}]";
        case
1:
           
$decoratedType = Identifier::getShortName($this->decoratedObjects[0]->getType());
            return
"Context specific $decoratedType with tag [{$this->tag}]";
        default:
            return
"$length context specific objects with tag [{$this->tag}]";
        }
    }

    public function
getType()
    {
        return
ord($this->getIdentifier());
    }

    public function
getIdentifier()
    {
       
$identifier = Identifier::create(Identifier::CLASS_CONTEXT_SPECIFIC, true, $this->tag);

        return
is_int($identifier) ? chr($identifier) : $identifier;
    }

    public function
getTag()
    {
        return
$this->tag;
    }

    public static function
fromBinary(&$binaryData, &$offsetIndex = 0)
    {
       
$identifier = self::parseBinaryIdentifier($binaryData, $offsetIndex);
       
$firstIdentifierOctet = ord($identifier);
       
assert(Identifier::isContextSpecificClass($firstIdentifierOctet), 'identifier octet should indicate context specific class');
       
assert(Identifier::isConstructed($firstIdentifierOctet), 'identifier octet should indicate constructed object');
       
$tag = Identifier::getTagNumber($identifier);

       
$totalContentLength = self::parseContentLength($binaryData, $offsetIndex);
       
$remainingContentLength = $totalContentLength;

       
$offsetIndexOfDecoratedObject = $offsetIndex;
       
$decoratedObjects = [];

        while (
$remainingContentLength > 0) {
           
$nextObject = ASNObject::fromBinary($binaryData, $offsetIndex);
           
$remainingContentLength -= $nextObject->getObjectLength();
           
$decoratedObjects[] = $nextObject;
        }

        if (
$remainingContentLength != 0) {
            throw new
ParserException("Context-Specific explicitly tagged object [$tag] starting at offset $offsetIndexOfDecoratedObject specifies a length of $totalContentLength octets but $remainingContentLength remain after parsing the content", $offsetIndexOfDecoratedObject);
        }

       
$parsedObject = new self($tag, ...$decoratedObjects);
       
$parsedObject->setContentLength($totalContentLength);
        return
$parsedObject;
    }
}