Passed
Push — main ( 70311e...ce1164 )
by smiley
03:37
created

ID3v2Abstract::getFrameLength()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 2
rs 10
1
<?php
2
/**
3
 * Class ID3v2Abstract
4
 *
5
 * @created      22.09.2018
6
 * @author       smiley <[email protected]>
7
 * @copyright    2018 smiley
8
 * @license      MIT
9
 */
10
11
namespace chillerlan\ID3Tag;
12
13
use function bin2hex, call_user_func_array, method_exists, ord, preg_match, strpos, substr, trim;
14
15
/**
16
 * @link http://id3.org/id3guide
17
 * @link http://id3.org/id3v2-chapters-1.0
18
 * @link http://id3.org/id3v2-accessibility-1.0
19
 * @link https://sno.phy.queensu.ca/~phil/exiftool/TagNames/ID3.html
20
 */
21
abstract class ID3v2Abstract implements ParserInterface{
22
23
	/**
24
	 * 4.15. Attached picture
25
	 *
26
	 * Picture type
27
	 *
28
	 * @var array
29
	 */
30
	public const PICTURE_TYPE = [
31
		0x00 => 'Other',
32
		0x01 => '32x32 pixels \'file icon\' (PNG only)',
33
		0x02 => 'Other file icon',
34
		0x03 => 'Cover (front)',
35
		0x04 => 'Cover (back)',
36
		0x05 => 'Leaflet page',
37
		0x06 => 'Media (e.g. label side of CD)',
38
		0x07 => 'Lead artist/lead performer/soloist',
39
		0x08 => 'Artist/performer',
40
		0x09 => 'Conductor',
41
		0x0A => 'Band/Orchestra',
42
		0x0B => 'Composer',
43
		0x0C => 'Lyricist/text writer',
44
		0x0D => 'Recording Location',
45
		0x0E => 'During recording',
46
		0x0F => 'During performance',
47
		0x10 => 'Movie/video screen capture',
48
		0x11 => 'A bright coloured fish',
49
		0x12 => 'Illustration',
50
		0x13 => 'Band/artist logotype',
51
		0x14 => 'Publisher/Studio logotype',
52
	];
53
54
	/**
55
	 * @var array
56
	 */
57
	public const ENCODING_NAMES = [
58
		// $00  ISO-8859-1.
59
		// Terminated with $00.
60
		0x00   => 'ISO-8859-1',
61
		// $01  UTF-16 encoded Unicode with BOM. All strings in the same frame SHALL have the same byteorder.
62
		// Terminated with $00 00.
63
		0x01   => 'UTF-16',
64
		// $02  UTF-16 big endian, encoded Unicode without BOM.
65
		// Terminated with $00 00.
66
		0x02   => 'UTF-16BE',
67
		// $03  UTF-8 encoded Unicode.
68
		// Terminated with $00.
69
		0x03   => 'UTF-8',
70
	];
71
72
	/**
73
	 * @var array
74
	 */
75
	protected const imageFormatMagicbytes = [
76
		'png'  => "\x89\x50\x4e\x47",
77
		'jpg'  => "\xff\xd8",
78
		'gif'  => "\x47\x49\x46\x38",
79
		'bmp'  => "\x42\x4d",
80
	];
81
82
	protected array $parsedFrames;
83
	protected array $declaredFrames;
84
	protected string $encoding;
85
	protected string $terminator = "\x00";
86
	protected int $termpos;
87
88
	/**
89
	 *
90
	 */
91
	protected function setTermpos(string $data):void{
92
		$encodingByte   = ord(substr($data, 0, 1));
93
		$this->encoding = $this::ENCODING_NAMES[$encodingByte] ?? 'ISO-8859-1';
94
		$this->termpos  = strpos($data, $this->terminator, 1);
95
96
		// UTF-16
97
		if($encodingByte === 1 || $encodingByte === 2){
98
			$this->terminator = "\x00\x00";
99
100
			// match terminator + BOM
101
			preg_match('/[\x00]{2}[\xfe\xff]{2}/', $data, $match);
102
103
			// no BOM / content following the terminator is not encoded
104
			if(empty($match) || $encodingByte === 2){
105
				preg_match('/[\x00]{2}[^\x00]+/', $data, $match);
106
			}
107
108
			$this->termpos = strpos($data, $match[0] ?? "\x00") + 2; // add 2 bytes for the terminator
109
		}
110
111
	}
112
113
	/**
114
	 *
115
	 */
116
	protected function decodeString(string $data):string{
117
		return trim(mb_convert_encoding($data, 'UTF-8', $this->encoding));
0 ignored issues
show
Bug introduced by
It seems like mb_convert_encoding($dat...TF-8', $this->encoding) can also be of type array; however, parameter $string of trim() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

117
		return trim(/** @scrutinizer ignore-type */ mb_convert_encoding($data, 'UTF-8', $this->encoding));
Loading history...
118
	}
119
120
	/**
121
	 *
122
	 */
123
	protected function parseFrame(array $frame):array{
124
125
		if(method_exists($this, $frame['name'])){
126
			return call_user_func_array([$this, $frame['name']], [$frame]);
127
		}
128
129
		$shortname = substr($frame['name'], 0, 1);
130
131
		if(method_exists($this, $shortname)){
132
			return call_user_func_array([$this, $shortname], [$frame]);
133
		}
134
135
		$frame['data'] = bin2hex($frame['data']);
136
137
		return ['rawdata' => $frame];
138
	}
139
140
	/**
141
	 *
142
	 */
143
	protected function addFrame(string $frameName, array $parsedFrame):void{
144
145
		if(empty($parsedFrame)){
146
			return;
147
		}
148
149
		$this->parsedFrames[] = [
150
			'name'     => $frameName,
151
			'info'     => $this->declaredFrames[$frameName] ?? '',
152
			'encoding' => $this->encoding
153
		] + $parsedFrame;
154
	}
155
156
}
157