Completed
Push — id3-metadata-objects ( e37014...ee91c4 )
by Daniel
12:20
created

ExtendedHeaderReader::readPadding()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 10
ccs 0
cts 5
cp 0
rs 9.4285
cc 2
eloc 5
nc 2
nop 0
crap 6
1
<?php
2
/**
3
 * This file is part of the Metadata package.
4
 *
5
 * @author Daniel Schröder <[email protected]>
6
 */
7
8
namespace GravityMedia\Metadata\ID3v2\Reader;
9
10
use GravityMedia\Metadata\ID3v2\Flag\ExtendedHeaderFlag;
11
use GravityMedia\Metadata\ID3v2\Restriction;
12
use GravityMedia\Metadata\ID3v2\Version;
13
14
/**
15
 * ID3v2 extended header reader class.
16
 *
17
 * @package GravityMedia\Metadata\ID3v2\Reader
18
 */
19
class ExtendedHeaderReader extends AbstractReader
20
{
21
    /**
22
     * @var int
23
     */
24
    private $padding;
25
26
    /**
27
     * @var int
28
     */
29
    private $crc32;
30
31
    /**
32
     * @var int[]
33
     */
34
    private $restrictions;
35
36
    /**
37
     * Read ID3v2 extended header size.
38
     *
39
     * @return int
40
     */
41
    protected function readSize()
42
    {
43
        $this->getStream()->seek($this->getOffset());
44
45
        $value = $this->getStream()->readUInt32();
46
47
        if (Version::VERSION_23 === $this->getVersion()) {
48
            return $value;
49
        }
50
51
        return $this->getSynchsafeIntegerFilter()->decode($value);
52
    }
53
54
    /**
55
     * Read ID3v2 extended header flags.
56
     *
57
     * @return bool[]
58
     */
59
    public function readFlags()
60
    {
61
        if (Version::VERSION_23 === $this->getVersion()) {
62
            $this->getStream()->seek($this->getOffset() + 4);
63
64
            $flags = $this->getStream()->readUInt16();
65
66
            return [
67
                ExtendedHeaderFlag::FLAG_CRC_DATA_PRESENT => (bool)($flags & 0x8000)
68
            ];
69
        }
70
71
        $this->getStream()->seek($this->getOffset() + 5);
72
73
        $flags = $this->getStream()->readUInt8();
74
75
        return [
76
            ExtendedHeaderFlag::FLAG_TAG_IS_AN_UPDATE => (bool)($flags & 0x40),
77
            ExtendedHeaderFlag::FLAG_CRC_DATA_PRESENT => (bool)($flags & 0x20),
78
            ExtendedHeaderFlag::FLAG_TAG_RESTRICTIONS => (bool)($flags & 0x10)
79
        ];
80
    }
81
82
    /**
83
     * Read ID3v2 extended header padding.
84
     *
85
     * @return int
86
     */
87
    protected function readPadding()
88
    {
89
        if (Version::VERSION_24 === $this->getVersion()) {
90
            return 0;
91
        }
92
93
        $this->getStream()->seek($this->getOffset() + 6);
94
95
        return $this->getStream()->readUInt32();
96
    }
97
98
    /**
99
     * Get ID3v2 extended header padding.
100
     *
101
     * @return int
102
     */
103
    public function getPadding()
104
    {
105
        if (null === $this->padding) {
106
            $this->padding = $this->readPadding();
107
        }
108
109
        return $this->padding;
110
    }
111
112
    /**
113
     * Read ID3v2 extended header CRC-32 data.
114
     *
115
     * @return int
116
     */
117
    protected function readCrc32()
118
    {
119
        if (!$this->isFlagEnabled(ExtendedHeaderFlag::FLAG_CRC_DATA_PRESENT)) {
120
            return 0;
121
        }
122
123 View Code Duplication
        if (Version::VERSION_23 === $this->getVersion()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
124
            $this->getStream()->seek($this->getOffset() + 10);
125
126
            return $this->getStream()->readUInt32();
127
        }
128
129
        $offset = 7;
130
        if ($this->isFlagEnabled(ExtendedHeaderFlag::FLAG_TAG_IS_AN_UPDATE)) {
131
            $offset += 1;
132
        }
133
134
        $this->getStream()->seek($this->getOffset() + $offset);
135
136
        return $this->getStream()->readUInt8() * 0x10000000 +
137
        $this->getSynchsafeIntegerFilter()->decode($this->getStream()->readUInt32());
138
    }
139
140
    /**
141
     * Get ID3v2 extended header CRC-32 data.
142
     *
143
     * @return int
144
     */
145
    public function getCrc32()
146
    {
147
        if (null === $this->crc32) {
148
            $this->crc32 = $this->readCrc32();
149
        }
150
151
        return $this->crc32;
152
    }
153
154
    /**
155
     * Read ID3v2 extended header restrictions.
156
     *
157
     * @return int[]
158
     */
159
    protected function readRestrictions()
160
    {
161
        if (!$this->isFlagEnabled(ExtendedHeaderFlag::FLAG_TAG_RESTRICTIONS)) {
162
            return [];
163
        }
164
165
        $offset = 6;
166
        if ($this->isFlagEnabled(ExtendedHeaderFlag::FLAG_TAG_IS_AN_UPDATE)) {
167
            $offset += 1;
168
        }
169
        if ($this->isFlagEnabled(ExtendedHeaderFlag::FLAG_CRC_DATA_PRESENT)) {
170
            $offset += 6;
171
        }
172
173
        $this->getStream()->seek($this->getOffset() + $offset);
174
175
        $restrictions = $this->getStream()->readUInt8();
176
177
        return [
178
            Restriction::RESTRICTION_TAG_SIZE => ($restrictions & 0xc0) >> 6,
179
            Restriction::RESTRICTION_TEXT_ENCODING => ($restrictions & 0x20) >> 5,
180
            Restriction::RESTRICTION_TEXT_FIELDS_SIZE => ($restrictions & 0x18) >> 3,
181
            Restriction::RESTRICTION_IMAGE_ENCODING => ($restrictions & 0x04) >> 2,
182
            Restriction::RESTRICTION_IMAGE_SIZE => ($restrictions & 0x03) >> 0
183
        ];
184
    }
185
186
    /**
187
     * Get ID3v2 extended header restrictions.
188
     *
189
     * @return int[]
190
     */
191
    public function getRestrictions()
192
    {
193
        if (null === $this->restrictions) {
194
            $this->restrictions = $this->readRestrictions();
195
        }
196
197
        return $this->restrictions;
198
    }
199
}
200