1<?php
2namespace TYPO3\PharStreamWrapper\Phar;
3
4/*
5 * This file is part of the TYPO3 project.
6 *
7 * It is free software; you can redistribute it and/or modify it under the terms
8 * of the MIT License (MIT). For the full copyright and license information,
9 * please read the LICENSE file that was distributed with this source code.
10 *
11 * The TYPO3 project - inspiring people to share!
12 */
13
14use Brumann\Polyfill\Unserialize;
15
16class Manifest
17{
18    /**
19     * @param string $content
20     * @return self
21     * @see http://php.net/manual/en/phar.fileformat.phar.php
22     */
23    public static function fromContent($content)
24    {
25        $target = new static();
26        $target->manifestLength = Reader::resolveFourByteLittleEndian($content, 0);
27        $target->amountOfFiles = Reader::resolveFourByteLittleEndian($content, 4);
28        $target->flags = Reader::resolveFourByteLittleEndian($content, 10);
29        $target->aliasLength = Reader::resolveFourByteLittleEndian($content, 14);
30        $target->alias = substr($content, 18, $target->aliasLength);
31        $target->metaDataLength = Reader::resolveFourByteLittleEndian($content, 18 + $target->aliasLength);
32        $target->metaData = substr($content, 22 + $target->aliasLength, $target->metaDataLength);
33
34        $apiVersionNibbles = Reader::resolveTwoByteBigEndian($content, 8);
35        $target->apiVersion = implode('.', array(
36            ($apiVersionNibbles & 0xf000) >> 12,
37            ($apiVersionNibbles & 0x0f00) >> 8,
38            ($apiVersionNibbles & 0x00f0) >> 4,
39        ));
40
41        return $target;
42    }
43
44    /**
45     * @var int
46     */
47    private $manifestLength;
48
49    /**
50     * @var int
51     */
52    private $amountOfFiles;
53
54    /**
55     * @var string
56     */
57    private $apiVersion;
58
59    /**
60     * @var int
61     */
62    private $flags;
63
64    /**
65     * @var int
66     */
67    private $aliasLength;
68
69    /**
70     * @var string
71     */
72    private $alias;
73
74    /**
75     * @var int
76     */
77    private $metaDataLength;
78
79    /**
80     * @var string
81     */
82    private $metaData;
83
84    /**
85     * Avoid direct instantiation.
86     */
87    private function __construct()
88    {
89    }
90
91    /**
92     * @return int
93     */
94    public function getManifestLength()
95    {
96        return $this->manifestLength;
97    }
98
99    /**
100     * @return int
101     */
102    public function getAmountOfFiles()
103    {
104        return $this->amountOfFiles;
105    }
106
107    /**
108     * @return string
109     */
110    public function getApiVersion()
111    {
112        return $this->apiVersion;
113    }
114
115    /**
116     * @return int
117     */
118    public function getFlags()
119    {
120        return $this->flags;
121    }
122
123    /**
124     * @return int
125     */
126    public function getAliasLength()
127    {
128        return $this->aliasLength;
129    }
130
131    /**
132     * @return string
133     */
134    public function getAlias()
135    {
136        return $this->alias;
137    }
138
139    /**
140     * @return int
141     */
142    public function getMetaDataLength()
143    {
144        return $this->metaDataLength;
145    }
146
147    /**
148     * @return string
149     */
150    public function getMetaData()
151    {
152        return $this->metaData;
153    }
154
155    /**
156     * @return mixed|null
157     */
158    public function deserializeMetaData()
159    {
160        if (empty($this->metaData)) {
161            return null;
162        }
163
164        $result = Unserialize::unserialize($this->metaData, array('allowed_classes' => false));
165
166        $serialized = json_encode($result);
167        if (strpos($serialized, '__PHP_Incomplete_Class_Name') !== false) {
168            throw new DeserializationException(
169                'Meta-data contains serialized object',
170                1539623382
171            );
172        }
173
174        return $result;
175    }
176}
177