Completed
Push — vendor/getid3 ( 1ec141...e63377 )
by Pauli
04:01
created

getid3_flac::parseSTREAMINFO()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 1
dl 0
loc 27
rs 9.488
c 0
b 0
f 0
1
<?php
2
3
/////////////////////////////////////////////////////////////////
4
/// getID3() by James Heinrich <[email protected]>               //
5
//  available at https://github.com/JamesHeinrich/getID3       //
6
//            or https://www.getid3.org                        //
7
//            or http://getid3.sourceforge.net                 //
8
//  see readme.txt for more details                            //
9
/////////////////////////////////////////////////////////////////
10
//                                                             //
11
// module.audio.flac.php                                       //
12
// module for analyzing FLAC and OggFLAC audio files           //
13
// dependencies: module.audio.ogg.php                          //
14
//                                                            ///
15
/////////////////////////////////////////////////////////////////
16
17
18
getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio.ogg.php', __FILE__, true);
19
20
/**
21
* @tutorial http://flac.sourceforge.net/format.html
22
*/
23
class getid3_flac extends getid3_handler
24
{
25
	const syncword = 'fLaC';
26
27
	/**
28
	 * @return bool
29
	 */
30
	public function Analyze() {
31
		$info = &$this->getid3->info;
32
33
		$this->fseek($info['avdataoffset']);
34
		$StreamMarker = $this->fread(4);
35
		if ($StreamMarker != self::syncword) {
36
			return $this->error('Expecting "'.getid3_lib::PrintHexBytes(self::syncword).'" at offset '.$info['avdataoffset'].', found "'.getid3_lib::PrintHexBytes($StreamMarker).'"');
0 ignored issues
show
Security Bug introduced by
It seems like $StreamMarker defined by $this->fread(4) on line 34 can also be of type false; however, getid3_lib::PrintHexBytes() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
37
		}
38
		$info['fileformat']            = 'flac';
39
		$info['audio']['dataformat']   = 'flac';
40
		$info['audio']['bitrate_mode'] = 'vbr';
41
		$info['audio']['lossless']     = true;
42
43
		// parse flac container
44
		return $this->parseMETAdata();
45
	}
46
47
	/**
48
	 * @return bool
49
	 */
50
	public function parseMETAdata() {
51
		$info = &$this->getid3->info;
52
		do {
53
			$BlockOffset   = $this->ftell();
54
			$BlockHeader   = $this->fread(4);
55
			$LBFBT         = getid3_lib::BigEndian2Int(substr($BlockHeader, 0, 1));  // LBFBT = LastBlockFlag + BlockType
56
			$LastBlockFlag = (bool) ($LBFBT & 0x80);
57
			$BlockType     =        ($LBFBT & 0x7F);
58
			$BlockLength   = getid3_lib::BigEndian2Int(substr($BlockHeader, 1, 3));
59
			$BlockTypeText = self::metaBlockTypeLookup($BlockType);
60
61
			if (($BlockOffset + 4 + $BlockLength) > $info['avdataend']) {
62
				$this->warning('METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockTypeText.') at offset '.$BlockOffset.' extends beyond end of file');
63
				break;
64
			}
65
			if ($BlockLength < 1) {
66
				if ($BlockTypeText != 'reserved') {
67
					// probably supposed to be zero-length
68
					$this->warning('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockTypeText.') at offset '.$BlockOffset.' is zero bytes');
69
					continue;
70
				}
71
				$this->error('METADATA_BLOCK_HEADER.BLOCK_LENGTH ('.$BlockLength.') at offset '.$BlockOffset.' is invalid');
72
				break;
73
			}
74
75
			$info['flac'][$BlockTypeText]['raw'] = array();
76
			$BlockTypeText_raw = &$info['flac'][$BlockTypeText]['raw'];
77
78
			$BlockTypeText_raw['offset']          = $BlockOffset;
79
			$BlockTypeText_raw['last_meta_block'] = $LastBlockFlag;
80
			$BlockTypeText_raw['block_type']      = $BlockType;
81
			$BlockTypeText_raw['block_type_text'] = $BlockTypeText;
82
			$BlockTypeText_raw['block_length']    = $BlockLength;
83
			if ($BlockTypeText_raw['block_type'] != 0x06) { // do not read attachment data automatically
84
				$BlockTypeText_raw['block_data']  = $this->fread($BlockLength);
0 ignored issues
show
Bug introduced by
It seems like $BlockLength defined by \getid3_lib::BigEndian2I...tr($BlockHeader, 1, 3)) on line 58 can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
85
			}
86
87
			switch ($BlockTypeText) {
88
				case 'STREAMINFO':     // 0x00
89
					if (!$this->parseSTREAMINFO($BlockTypeText_raw['block_data'])) {
90
						return false;
91
					}
92
					break;
93
94
				case 'PADDING':        // 0x01
95
					unset($info['flac']['PADDING']); // ignore
96
					break;
97
98
				case 'APPLICATION':    // 0x02
99
					if (!$this->parseAPPLICATION($BlockTypeText_raw['block_data'])) {
100
						return false;
101
					}
102
					break;
103
104
				case 'SEEKTABLE':      // 0x03
105
					if (!$this->parseSEEKTABLE($BlockTypeText_raw['block_data'])) {
106
						return false;
107
					}
108
					break;
109
110
				case 'VORBIS_COMMENT': // 0x04
111
					if (!$this->parseVORBIS_COMMENT($BlockTypeText_raw['block_data'])) {
112
						return false;
113
					}
114
					break;
115
116
				case 'CUESHEET':       // 0x05
117
					if (!$this->parseCUESHEET($BlockTypeText_raw['block_data'])) {
118
						return false;
119
					}
120
					break;
121
122
				case 'PICTURE':        // 0x06
123
					if (!$this->parsePICTURE()) {
124
						return false;
125
					}
126
					break;
127
128
				default:
129
					$this->warning('Unhandled METADATA_BLOCK_HEADER.BLOCK_TYPE ('.$BlockType.') at offset '.$BlockOffset);
130
			}
131
132
			unset($info['flac'][$BlockTypeText]['raw']);
133
			$info['avdataoffset'] = $this->ftell();
134
		}
135
		while ($LastBlockFlag === false);
136
137
		// handle tags
138
		if (!empty($info['flac']['VORBIS_COMMENT']['comments'])) {
139
			$info['flac']['comments'] = $info['flac']['VORBIS_COMMENT']['comments'];
140
		}
141
		if (!empty($info['flac']['VORBIS_COMMENT']['vendor'])) {
142
			$info['audio']['encoder'] = str_replace('reference ', '', $info['flac']['VORBIS_COMMENT']['vendor']);
143
		}
144
145
		// copy attachments to 'comments' array if nesesary
146
		if (isset($info['flac']['PICTURE']) && ($this->getid3->option_save_attachments !== getID3::ATTACHMENTS_NONE)) {
147
			foreach ($info['flac']['PICTURE'] as $entry) {
148 View Code Duplication
				if (!empty($entry['data'])) {
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...
149
					if (!isset($info['flac']['comments']['picture'])) {
150
						$info['flac']['comments']['picture'] = array();
151
					}
152
					$comments_picture_data = array();
153
					foreach (array('data', 'image_mime', 'image_width', 'image_height', 'imagetype', 'picturetype', 'description', 'datalength') as $picture_key) {
154
						if (isset($entry[$picture_key])) {
155
							$comments_picture_data[$picture_key] = $entry[$picture_key];
156
						}
157
					}
158
					$info['flac']['comments']['picture'][] = $comments_picture_data;
159
					unset($comments_picture_data);
160
				}
161
			}
162
		}
163
164
		if (isset($info['flac']['STREAMINFO'])) {
165
			if (!$this->isDependencyFor('matroska')) {
166
				$info['flac']['compressed_audio_bytes'] = $info['avdataend'] - $info['avdataoffset'];
167
			}
168
			$info['flac']['uncompressed_audio_bytes'] = $info['flac']['STREAMINFO']['samples_stream'] * $info['flac']['STREAMINFO']['channels'] * ($info['flac']['STREAMINFO']['bits_per_sample'] / 8);
169
			if ($info['flac']['uncompressed_audio_bytes'] == 0) {
170
				return $this->error('Corrupt FLAC file: uncompressed_audio_bytes == zero');
171
			}
172
			if (!empty($info['flac']['compressed_audio_bytes'])) {
173
				$info['flac']['compression_ratio'] = $info['flac']['compressed_audio_bytes'] / $info['flac']['uncompressed_audio_bytes'];
174
			}
175
		}
176
177
		// set md5_data_source - built into flac 0.5+
178
		if (isset($info['flac']['STREAMINFO']['audio_signature'])) {
179
180
			if ($info['flac']['STREAMINFO']['audio_signature'] === str_repeat("\x00", 16)) {
181
                $this->warning('FLAC STREAMINFO.audio_signature is null (known issue with libOggFLAC)');
182
			}
183 View Code Duplication
			else {
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...
184
				$info['md5_data_source'] = '';
185
				$md5 = $info['flac']['STREAMINFO']['audio_signature'];
186
				for ($i = 0; $i < strlen($md5); $i++) {
187
					$info['md5_data_source'] .= str_pad(dechex(ord($md5[$i])), 2, '00', STR_PAD_LEFT);
188
				}
189
				if (!preg_match('/^[0-9a-f]{32}$/', $info['md5_data_source'])) {
190
					unset($info['md5_data_source']);
191
				}
192
			}
193
		}
194
195
		if (isset($info['flac']['STREAMINFO']['bits_per_sample'])) {
196
			$info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
197
			if ($info['audio']['bits_per_sample'] == 8) {
198
				// special case
199
				// must invert sign bit on all data bytes before MD5'ing to match FLAC's calculated value
200
				// MD5sum calculates on unsigned bytes, but FLAC calculated MD5 on 8-bit audio data as signed
201
				$this->warning('FLAC calculates MD5 data strangely on 8-bit audio, so the stored md5_data_source value will not match the decoded WAV file');
202
			}
203
		}
204
205
		return true;
206
	}
207
208
209
	/**
210
	 * @param string $BlockData
211
	 *
212
	 * @return array
213
	 */
214
	public static function parseSTREAMINFOdata($BlockData) {
215
		$streaminfo = array();
216
		$streaminfo['min_block_size']  = getid3_lib::BigEndian2Int(substr($BlockData, 0, 2));
217
		$streaminfo['max_block_size']  = getid3_lib::BigEndian2Int(substr($BlockData, 2, 2));
218
		$streaminfo['min_frame_size']  = getid3_lib::BigEndian2Int(substr($BlockData, 4, 3));
219
		$streaminfo['max_frame_size']  = getid3_lib::BigEndian2Int(substr($BlockData, 7, 3));
220
221
		$SRCSBSS                       = getid3_lib::BigEndian2Bin(substr($BlockData, 10, 8));
222
		$streaminfo['sample_rate']     = getid3_lib::Bin2Dec(substr($SRCSBSS,  0, 20));
223
		$streaminfo['channels']        = getid3_lib::Bin2Dec(substr($SRCSBSS, 20,  3)) + 1;
224
		$streaminfo['bits_per_sample'] = getid3_lib::Bin2Dec(substr($SRCSBSS, 23,  5)) + 1;
225
		$streaminfo['samples_stream']  = getid3_lib::Bin2Dec(substr($SRCSBSS, 28, 36));
226
227
		$streaminfo['audio_signature'] =                           substr($BlockData, 18, 16);
228
229
		return $streaminfo;
230
	}
231
232
	/**
233
	 * @param string $BlockData
234
	 *
235
	 * @return bool
236
	 */
237
	private function parseSTREAMINFO($BlockData) {
238
		$info = &$this->getid3->info;
239
240
		$info['flac']['STREAMINFO'] = self::parseSTREAMINFOdata($BlockData);
241
242
		if (!empty($info['flac']['STREAMINFO']['sample_rate'])) {
243
244
			$info['audio']['bitrate_mode']    = 'vbr';
245
			$info['audio']['sample_rate']     = $info['flac']['STREAMINFO']['sample_rate'];
246
			$info['audio']['channels']        = $info['flac']['STREAMINFO']['channels'];
247
			$info['audio']['bits_per_sample'] = $info['flac']['STREAMINFO']['bits_per_sample'];
248
			$info['playtime_seconds']         = $info['flac']['STREAMINFO']['samples_stream'] / $info['flac']['STREAMINFO']['sample_rate'];
249
			if ($info['playtime_seconds'] > 0) {
250
				if (!$this->isDependencyFor('matroska')) {
251
					$info['audio']['bitrate'] = (($info['avdataend'] - $info['avdataoffset']) * 8) / $info['playtime_seconds'];
252
				}
253
				else {
254
					$this->warning('Cannot determine audio bitrate because total stream size is unknown');
255
				}
256
			}
257
258
		} else {
259
			return $this->error('Corrupt METAdata block: STREAMINFO');
260
		}
261
262
		return true;
263
	}
264
265
	/**
266
	 * @param string $BlockData
267
	 *
268
	 * @return bool
269
	 */
270
	private function parseAPPLICATION($BlockData) {
271
		$info = &$this->getid3->info;
272
273
		$ApplicationID = getid3_lib::BigEndian2Int(substr($BlockData, 0, 4));
274
		$info['flac']['APPLICATION'][$ApplicationID]['name'] = self::applicationIDLookup($ApplicationID);
0 ignored issues
show
Bug introduced by
It seems like $ApplicationID defined by \getid3_lib::BigEndian2I...bstr($BlockData, 0, 4)) on line 273 can also be of type double or false; however, getid3_flac::applicationIDLookup() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
275
		$info['flac']['APPLICATION'][$ApplicationID]['data'] = substr($BlockData, 4);
276
277
		return true;
278
	}
279
280
	/**
281
	 * @param string $BlockData
282
	 *
283
	 * @return bool
284
	 */
285
	private function parseSEEKTABLE($BlockData) {
286
		$info = &$this->getid3->info;
287
288
		$offset = 0;
289
		$BlockLength = strlen($BlockData);
290
		$placeholderpattern = str_repeat("\xFF", 8);
291
		while ($offset < $BlockLength) {
292
			$SampleNumberString = substr($BlockData, $offset, 8);
293
			$offset += 8;
294
			if ($SampleNumberString == $placeholderpattern) {
295
296
				// placeholder point
297
				getid3_lib::safe_inc($info['flac']['SEEKTABLE']['placeholders'], 1);
298
				$offset += 10;
299
300
			} else {
301
302
				$SampleNumber                                        = getid3_lib::BigEndian2Int($SampleNumberString);
303
				$info['flac']['SEEKTABLE'][$SampleNumber]['offset']  = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8));
304
				$offset += 8;
305
				$info['flac']['SEEKTABLE'][$SampleNumber]['samples'] = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 2));
306
				$offset += 2;
307
308
			}
309
		}
310
311
		return true;
312
	}
313
314
	/**
315
	 * @param string $BlockData
316
	 *
317
	 * @return bool
318
	 */
319
	private function parseVORBIS_COMMENT($BlockData) {
0 ignored issues
show
Unused Code introduced by
The parameter $BlockData is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
320
		$info = &$this->getid3->info;
321
322
		$getid3_ogg = new getid3_ogg($this->getid3);
323
		if ($this->isDependencyFor('matroska')) {
324
			$getid3_ogg->setStringMode($this->data_string);
325
		}
326
		$getid3_ogg->ParseVorbisComments();
327
		if (isset($info['ogg'])) {
328
			unset($info['ogg']['comments_raw']);
329
			$info['flac']['VORBIS_COMMENT'] = $info['ogg'];
330
			unset($info['ogg']);
331
		}
332
333
		unset($getid3_ogg);
334
335
		return true;
336
	}
337
338
	/**
339
	 * @param string $BlockData
340
	 *
341
	 * @return bool
342
	 */
343
	private function parseCUESHEET($BlockData) {
344
		$info = &$this->getid3->info;
345
		$offset = 0;
346
		$info['flac']['CUESHEET']['media_catalog_number'] =                              trim(substr($BlockData, $offset, 128), "\0");
347
		$offset += 128;
348
		$info['flac']['CUESHEET']['lead_in_samples']      =         getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8));
349
		$offset += 8;
350
		$info['flac']['CUESHEET']['flags']['is_cd']       = (bool) (getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1)) & 0x80);
351
		$offset += 1;
352
353
		$offset += 258; // reserved
354
355
		$info['flac']['CUESHEET']['number_tracks']        =         getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1));
356
		$offset += 1;
357
358
		for ($track = 0; $track < $info['flac']['CUESHEET']['number_tracks']; $track++) {
359
			$TrackSampleOffset = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8));
360
			$offset += 8;
361
			$TrackNumber       = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1));
362
			$offset += 1;
363
364
			$info['flac']['CUESHEET']['tracks'][$TrackNumber]['sample_offset']         = $TrackSampleOffset;
365
366
			$info['flac']['CUESHEET']['tracks'][$TrackNumber]['isrc']                  =                           substr($BlockData, $offset, 12);
367
			$offset += 12;
368
369
			$TrackFlagsRaw                                                             = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1));
370
			$offset += 1;
371
			$info['flac']['CUESHEET']['tracks'][$TrackNumber]['flags']['is_audio']     = (bool) ($TrackFlagsRaw & 0x80);
372
			$info['flac']['CUESHEET']['tracks'][$TrackNumber]['flags']['pre_emphasis'] = (bool) ($TrackFlagsRaw & 0x40);
373
374
			$offset += 13; // reserved
375
376
			$info['flac']['CUESHEET']['tracks'][$TrackNumber]['index_points']          = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1));
377
			$offset += 1;
378
379 View Code Duplication
			for ($index = 0; $index < $info['flac']['CUESHEET']['tracks'][$TrackNumber]['index_points']; $index++) {
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...
380
				$IndexSampleOffset = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 8));
381
				$offset += 8;
382
				$IndexNumber       = getid3_lib::BigEndian2Int(substr($BlockData, $offset, 1));
383
				$offset += 1;
384
385
				$offset += 3; // reserved
386
387
				$info['flac']['CUESHEET']['tracks'][$TrackNumber]['indexes'][$IndexNumber] = $IndexSampleOffset;
388
			}
389
		}
390
391
		return true;
392
	}
393
394
	/**
395
	 * Parse METADATA_BLOCK_PICTURE flac structure and extract attachment
396
	 * External usage: audio.ogg
397
	 *
398
	 * @return bool
399
	 */
400
	public function parsePICTURE() {
401
		$info = &$this->getid3->info;
402
403
		$picture['typeid']         = getid3_lib::BigEndian2Int($this->fread(4));
0 ignored issues
show
Coding Style Comprehensibility introduced by
$picture was never initialized. Although not strictly required by PHP, it is generally a good practice to add $picture = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
Security Bug introduced by
It seems like $this->fread(4) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
404
		$picture['picturetype']    = self::pictureTypeLookup($picture['typeid']);
0 ignored issues
show
Bug introduced by
It seems like $picture['typeid'] can also be of type double or false; however, getid3_flac::pictureTypeLookup() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
405
		$picture['image_mime']     = $this->fread(getid3_lib::BigEndian2Int($this->fread(4)));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(4) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
Bug introduced by
It seems like \getid3_lib::BigEndian2Int($this->fread(4)) targeting getid3_lib::BigEndian2Int() can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
406
		$descr_length              = getid3_lib::BigEndian2Int($this->fread(4));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(4) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
407
		if ($descr_length) {
408
			$picture['description'] = $this->fread($descr_length);
409
		}
410
		$picture['image_width']    = getid3_lib::BigEndian2Int($this->fread(4));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(4) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
411
		$picture['image_height']   = getid3_lib::BigEndian2Int($this->fread(4));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(4) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
412
		$picture['color_depth']    = getid3_lib::BigEndian2Int($this->fread(4));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(4) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
413
		$picture['colors_indexed'] = getid3_lib::BigEndian2Int($this->fread(4));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(4) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
414
		$picture['datalength']     = getid3_lib::BigEndian2Int($this->fread(4));
0 ignored issues
show
Security Bug introduced by
It seems like $this->fread(4) targeting getid3_handler::fread() can also be of type false; however, getid3_lib::BigEndian2Int() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
415
416
		if ($picture['image_mime'] == '-->') {
417
			$picture['data'] = $this->fread($picture['datalength']);
0 ignored issues
show
Bug introduced by
It seems like $picture['datalength'] can also be of type double or false; however, getid3_handler::fread() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
418
		} else {
419
			$picture['data'] = $this->saveAttachment(
420
				str_replace('/', '_', $picture['picturetype']).'_'.$this->ftell(),
421
				$this->ftell(),
0 ignored issues
show
Bug introduced by
It seems like $this->ftell() targeting getid3_handler::ftell() can also be of type boolean; however, getid3_handler::saveAttachment() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
422
				$picture['datalength'],
0 ignored issues
show
Bug introduced by
It seems like $picture['datalength'] can also be of type double or false; however, getid3_handler::saveAttachment() does only seem to accept integer, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
423
				$picture['image_mime']);
424
		}
425
426
		$info['flac']['PICTURE'][] = $picture;
427
428
		return true;
429
	}
430
431
	/**
432
	 * @param int $blocktype
433
	 *
434
	 * @return string
435
	 */
436
	public static function metaBlockTypeLookup($blocktype) {
437
		static $lookup = array(
438
			0 => 'STREAMINFO',
439
			1 => 'PADDING',
440
			2 => 'APPLICATION',
441
			3 => 'SEEKTABLE',
442
			4 => 'VORBIS_COMMENT',
443
			5 => 'CUESHEET',
444
			6 => 'PICTURE',
445
		);
446
		return (isset($lookup[$blocktype]) ? $lookup[$blocktype] : 'reserved');
447
	}
448
449
	/**
450
	 * @param int $applicationid
451
	 *
452
	 * @return string
453
	 */
454
	public static function applicationIDLookup($applicationid) {
455
		// http://flac.sourceforge.net/id.html
456
		static $lookup = array(
457
			0x41544348 => 'FlacFile',                                                                           // "ATCH"
458
			0x42534F4C => 'beSolo',                                                                             // "BSOL"
459
			0x42554753 => 'Bugs Player',                                                                        // "BUGS"
460
			0x43756573 => 'GoldWave cue points (specification)',                                                // "Cues"
461
			0x46696361 => 'CUE Splitter',                                                                       // "Fica"
462
			0x46746F6C => 'flac-tools',                                                                         // "Ftol"
463
			0x4D4F5442 => 'MOTB MetaCzar',                                                                      // "MOTB"
464
			0x4D505345 => 'MP3 Stream Editor',                                                                  // "MPSE"
465
			0x4D754D4C => 'MusicML: Music Metadata Language',                                                   // "MuML"
466
			0x52494646 => 'Sound Devices RIFF chunk storage',                                                   // "RIFF"
467
			0x5346464C => 'Sound Font FLAC',                                                                    // "SFFL"
468
			0x534F4E59 => 'Sony Creative Software',                                                             // "SONY"
469
			0x5351455A => 'flacsqueeze',                                                                        // "SQEZ"
470
			0x54745776 => 'TwistedWave',                                                                        // "TtWv"
471
			0x55495453 => 'UITS Embedding tools',                                                               // "UITS"
472
			0x61696666 => 'FLAC AIFF chunk storage',                                                            // "aiff"
473
			0x696D6167 => 'flac-image application for storing arbitrary files in APPLICATION metadata blocks',  // "imag"
474
			0x7065656D => 'Parseable Embedded Extensible Metadata (specification)',                             // "peem"
475
			0x71667374 => 'QFLAC Studio',                                                                       // "qfst"
476
			0x72696666 => 'FLAC RIFF chunk storage',                                                            // "riff"
477
			0x74756E65 => 'TagTuner',                                                                           // "tune"
478
			0x78626174 => 'XBAT',                                                                               // "xbat"
479
			0x786D6364 => 'xmcd',                                                                               // "xmcd"
480
		);
481
		return (isset($lookup[$applicationid]) ? $lookup[$applicationid] : 'reserved');
482
	}
483
484
	/**
485
	 * @param int $type_id
486
	 *
487
	 * @return string
488
	 */
489 View Code Duplication
	public static function pictureTypeLookup($type_id) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
490
		static $lookup = array (
491
			 0 => 'Other',
492
			 1 => '32x32 pixels \'file icon\' (PNG only)',
493
			 2 => 'Other file icon',
494
			 3 => 'Cover (front)',
495
			 4 => 'Cover (back)',
496
			 5 => 'Leaflet page',
497
			 6 => 'Media (e.g. label side of CD)',
498
			 7 => 'Lead artist/lead performer/soloist',
499
			 8 => 'Artist/performer',
500
			 9 => 'Conductor',
501
			10 => 'Band/Orchestra',
502
			11 => 'Composer',
503
			12 => 'Lyricist/text writer',
504
			13 => 'Recording Location',
505
			14 => 'During recording',
506
			15 => 'During performance',
507
			16 => 'Movie/video screen capture',
508
			17 => 'A bright coloured fish',
509
			18 => 'Illustration',
510
			19 => 'Band/artist logotype',
511
			20 => 'Publisher/Studio logotype',
512
		);
513
		return (isset($lookup[$type_id]) ? $lookup[$type_id] : 'reserved');
514
	}
515
516
}
517