Completed
Push — vendor/getid3 ( 69b815...49c253 )
by Pauli
04:26 queued 01:37
created

demo.mp3header.php ➔ md5_file()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 1
dl 0
loc 11
rs 9.9
c 0
b 0
f 0
1
<?php
2
/////////////////////////////////////////////////////////////////
3
/// getID3() by James Heinrich <[email protected]>               //
4
//  available at https://github.com/JamesHeinrich/getID3       //
5
//            or https://www.getid3.org                        //
6
//            or http://getid3.sourceforge.net                 //
7
//                                                             //
8
// /demo/demo.mp3header.php - part of getID3()                 //
9
// Sample script for decoding MP3 header bytes                 //
10
//  see readme.txt for more details                            //
11
//                                                            ///
12
/////////////////////////////////////////////////////////////////
13
14
if (!function_exists('PrintHexBytes')) {
15
	function PrintHexBytes($string) {
16
		$returnstring = '';
17
		for ($i = 0; $i < strlen($string); $i++) {
18
			$returnstring .= str_pad(dechex(ord(substr($string, $i, 1))), 2, '0', STR_PAD_LEFT).' ';
19
		}
20
		return $returnstring;
21
	}
22
}
23
24
if (!function_exists('PrintTextBytes')) {
25
	function PrintTextBytes($string) {
26
		$returnstring = '';
27
		for ($i = 0; $i < strlen($string); $i++) {
28
			if (ord(substr($string, $i, 1)) <= 31) {
29
				$returnstring .= '   ';
30
			} else {
31
				$returnstring .= ' '.substr($string, $i, 1).' ';
32
			}
33
		}
34
		return $returnstring;
35
	}
36
}
37
38
if (!function_exists('table_var_dump')) {
39
	function table_var_dump($variable) {
0 ignored issues
show
Best Practice introduced by
The function table_var_dump() has been defined more than once; this definition is ignored, only the first definition in 3rdparty/getID3/demos/demo.browse.php (L459-528) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
40
		$returnstring = '';
41
		switch (gettype($variable)) {
42
			case 'array':
43
				$returnstring .= '<table border="1" cellspacing="0" cellpadding="2">';
44
				foreach ($variable as $key => $value) {
45
					$returnstring .= '<tr><td valign="top"><b>'.str_replace(chr(0), ' ', $key).'</b></td>';
46
					$returnstring .= '<td valign="top">'.gettype($value);
47 View Code Duplication
					if (is_array($value)) {
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...
48
						$returnstring .= '&nbsp;('.count($value).')';
49
					} elseif (is_string($value)) {
50
						$returnstring .= '&nbsp;('.strlen($value).')';
51
					}
52
					if (($key == 'data') && isset($variable['image_mime']) && isset($variable['dataoffset'])) {
53
						require_once(GETID3_INCLUDEPATH.'getid3.getimagesize.php');
54
						$imageinfo = array();
55
						if ($imagechunkcheck = GetDataImageSize($value, $imageinfo)) {
56
							$DumpedImageSRC = (!empty($_REQUEST['filename']) ? $_REQUEST['filename'] : '.getid3').'.'.$variable['dataoffset'].'.'.image_type_to_mime_type($imagechunkcheck[2]);
57
							if ($tempimagefile = fopen($DumpedImageSRC, 'wb')) {
58
								fwrite($tempimagefile, $value);
59
								fclose($tempimagefile);
60
							}
61
							$returnstring .= '</td><td><img src="'.$DumpedImageSRC.'" width="'.$imagechunkcheck[0].'" height="'.$imagechunkcheck[1].'"></td></tr>';
62
						} else {
63
							$returnstring .= '</td><td><i>invalid image data</i></td></tr>';
64
						}
65
					} else {
66
						$returnstring .= '</td><td>'.table_var_dump($value).'</td></tr>';
67
					}
68
				}
69
				$returnstring .= '</table>';
70
				break;
71
72
			case 'boolean':
73
				$returnstring .= ($variable ? 'TRUE' : 'FALSE');
74
				break;
75
76
			case 'integer':
77
			case 'double':
78
			case 'float':
79
				$returnstring .= $variable;
80
				break;
81
82
			case 'object':
83
			case 'null':
84
				$returnstring .= string_var_dump($variable);
85
				break;
86
87
			case 'string':
88
				$variable = str_replace(chr(0), ' ', $variable);
89
				$varlen = strlen($variable);
90
				for ($i = 0; $i < $varlen; $i++) {
91
					if (preg_match('#['.chr(0x0A).chr(0x0D).' -;0-9A-Za-z]#', $variable[$i])) {
92
						$returnstring .= $variable[$i];
93
					} else {
94
						$returnstring .= '&#'.str_pad(ord($variable[$i]), 3, '0', STR_PAD_LEFT).';';
95
					}
96
				}
97
				$returnstring = nl2br($returnstring);
98
				break;
99
100
			default:
101
				require_once(GETID3_INCLUDEPATH.'getid3.getimagesize.php');
102
				$imageinfo = array();
103
				if (($imagechunkcheck = GetDataImageSize(substr($variable, 0, 32768), $imageinfo)) && ($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
104
					$returnstring .= '<table border="1" cellspacing="0" cellpadding="2">';
105
					$returnstring .= '<tr><td><b>type</b></td><td>'.image_type_to_mime_type($imagechunkcheck[2]).'</td></tr>';
106
					$returnstring .= '<tr><td><b>width</b></td><td>'.number_format($imagechunkcheck[0]).' px</td></tr>';
107
					$returnstring .= '<tr><td><b>height</b></td><td>'.number_format($imagechunkcheck[1]).' px</td></tr>';
108
					$returnstring .= '<tr><td><b>size</b></td><td>'.number_format(strlen($variable)).' bytes</td></tr></table>';
109
				} else {
110
					$returnstring .= nl2br(htmlspecialchars(str_replace(chr(0), ' ', $variable)));
111
				}
112
				break;
113
		}
114
		return $returnstring;
115
	}
116
}
117
118
if (!function_exists('string_var_dump')) {
119 View Code Duplication
	function string_var_dump($variable) {
0 ignored issues
show
Duplication introduced by
This function 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...
Best Practice introduced by
The function string_var_dump() has been defined more than once; this definition is ignored, only the first definition in 3rdparty/getID3/demos/demo.browse.php (L448-457) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
120
		if (version_compare(PHP_VERSION, '4.3.0', '>=')) {
121
			return print_r($variable, true);
122
		}
123
		ob_start();
124
		var_dump($variable);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($variable); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
125
		$dumpedvariable = ob_get_contents();
126
		ob_end_clean();
127
		return $dumpedvariable;
128
	}
129
}
130
131
if (!function_exists('fileextension')) {
132 View Code Duplication
	function fileextension($filename, $numextensions=1) {
0 ignored issues
show
Duplication introduced by
This function 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...
133
		if (strstr($filename, '.')) {
134
			$reversedfilename = strrev($filename);
135
			$offset = 0;
136
			for ($i = 0; $i < $numextensions; $i++) {
137
				$offset = strpos($reversedfilename, '.', $offset + 1);
138
				if ($offset === false) {
139
					return '';
140
				}
141
			}
142
			return strrev(substr($reversedfilename, 0, $offset));
143
		}
144
		return '';
145
	}
146
}
147
148
if (!function_exists('RemoveAccents')) {
149
	function RemoveAccents($string) {
0 ignored issues
show
Best Practice introduced by
The function RemoveAccents() has been defined more than once; this definition is ignored, only the first definition in 3rdparty/getID3/demos/demo.browse.php (L401-423) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
150
		// return strtr($string, 'ŠŒŽšœžŸ¥µÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýÿ', 'SOZsozYYuAAAAAAACEEEEIIIIDNOOOOOOUUUUYsaaaaaaaceeeeiiiionoooooouuuuyy');
151
		// Revised version by [email protected]
152
		return strtr(strtr($string, 'ŠŽšžŸÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÑÒÓÔÕÖØÙÚÛÜÝàáâãäåçèéêëìíîïñòóôõöøùúûüýÿ', 'SZszYAAAAAACEEEEIIIINOOOOOOUUUUYaaaaaaceeeeiiiinoooooouuuuyy'), array('Þ' => 'TH', 'þ' => 'th', 'Ð' => 'DH', 'ð' => 'dh', 'ß' => 'ss', 'Œ' => 'OE', 'œ' => 'oe', 'Æ' => 'AE', 'æ' => 'ae', 'µ' => 'u'));
153
	}
154
}
155
156
if (!function_exists('MoreNaturalSort')) {
157 View Code Duplication
	function MoreNaturalSort($ar1, $ar2) {
0 ignored issues
show
Duplication introduced by
This function 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...
Best Practice introduced by
The function MoreNaturalSort() has been defined more than once; this definition is ignored, only the first definition in 3rdparty/getID3/demos/demo.browse.php (L568-598) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
158
		if ($ar1 === $ar2) {
159
			return 0;
160
		}
161
		$len1     = strlen($ar1);
162
		$len2     = strlen($ar2);
163
		$shortest = min($len1, $len2);
164
		if (substr($ar1, 0, $shortest) === substr($ar2, 0, $shortest)) {
165
			// the shorter argument is the beginning of the longer one, like "str" and "string"
166
			if ($len1 < $len2) {
167
				return -1;
168
			} elseif ($len1 > $len2) {
169
				return 1;
170
			}
171
			return 0;
172
		}
173
		$ar1 = RemoveAccents(strtolower(trim($ar1)));
174
		$ar2 = RemoveAccents(strtolower(trim($ar2)));
175
		$translatearray = array('\''=>'', '"'=>'', '_'=>' ', '('=>'', ')'=>'', '-'=>' ', '  '=>' ', '.'=>'', ','=>'');
176
		foreach ($translatearray as $key => $val) {
177
			$ar1 = str_replace($key, $val, $ar1);
178
			$ar2 = str_replace($key, $val, $ar2);
179
		}
180
181
		if ($ar1 < $ar2) {
182
			return -1;
183
		} elseif ($ar1 > $ar2) {
184
			return 1;
185
		}
186
		return 0;
187
	}
188
}
189
190
if (!function_exists('trunc')) {
191 View Code Duplication
	function trunc($floatnumber) {
0 ignored issues
show
Duplication introduced by
This function 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...
192
		// truncates a floating-point number at the decimal point
193
		// returns int (if possible, otherwise float)
194
		if ($floatnumber >= 1) {
195
			$truncatednumber = floor($floatnumber);
196
		} elseif ($floatnumber <= -1) {
197
			$truncatednumber = ceil($floatnumber);
198
		} else {
199
			$truncatednumber = 0;
200
		}
201
		if ($truncatednumber <= pow(2, 30)) {
202
			$truncatednumber = (int) $truncatednumber;
203
		}
204
		return $truncatednumber;
205
	}
206
}
207
208
if (!function_exists('CastAsInt')) {
209
	function CastAsInt($floatnum) {
210
		// convert to float if not already
211
		$floatnum = (float) $floatnum;
212
213
		// convert a float to type int, only if possible
214
		if (trunc($floatnum) == $floatnum) {
215
			// it's not floating point
216
			if ($floatnum <= pow(2, 30)) {
217
				// it's within int range
218
				$floatnum = (int) $floatnum;
219
			}
220
		}
221
		return $floatnum;
222
	}
223
}
224
225
if (!function_exists('getmicrotime')) {
226
	function getmicrotime() {
227
		list($usec, $sec) = explode(' ', microtime());
228
		return ((float) $usec + (float) $sec);
229
	}
230
}
231
232
if (!function_exists('DecimalBinary2Float')) {
233
	function DecimalBinary2Float($binarynumerator) {
234
		$numerator   = Bin2Dec($binarynumerator);
235
		$denominator = Bin2Dec(str_repeat('1', strlen($binarynumerator)));
236
		return ($numerator / $denominator);
237
	}
238
}
239
240
if (!function_exists('NormalizeBinaryPoint')) {
241 View Code Duplication
	function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
0 ignored issues
show
Duplication introduced by
This function 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...
242
		// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
243
		if (strpos($binarypointnumber, '.') === false) {
244
			$binarypointnumber = '0.'.$binarypointnumber;
245
		} elseif ($binarypointnumber[0] == '.') {
246
			$binarypointnumber = '0'.$binarypointnumber;
247
		}
248
		$exponent = 0;
249
		while (($binarypointnumber[0] != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
250
			if (substr($binarypointnumber, 1, 1) == '.') {
251
				$exponent--;
252
				$binarypointnumber = substr($binarypointnumber, 2, 1).'.'.substr($binarypointnumber, 3);
253
			} else {
254
				$pointpos = strpos($binarypointnumber, '.');
255
				$exponent += ($pointpos - 1);
256
				$binarypointnumber = str_replace('.', '', $binarypointnumber);
257
				$binarypointnumber = $binarypointnumber[0].'.'.substr($binarypointnumber, 1);
258
			}
259
		}
260
		$binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT);
261
		return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent);
262
	}
263
}
264
265
if (!function_exists('Float2BinaryDecimal')) {
266
	function Float2BinaryDecimal($floatvalue) {
267
		// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
268
		$maxbits = 128; // to how many bits of precision should the calculations be taken?
269
		$intpart   = trunc($floatvalue);
270
		$floatpart = abs($floatvalue - $intpart);
271
		$pointbitstring = '';
272 View Code Duplication
		while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) {
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...
273
			$floatpart *= 2;
274
			$pointbitstring .= (string) trunc($floatpart);
275
			$floatpart -= trunc($floatpart);
276
		}
277
		$binarypointnumber = decbin($intpart).'.'.$pointbitstring;
278
		return $binarypointnumber;
279
	}
280
}
281
282
if (!function_exists('Float2String')) {
283
	function Float2String($floatvalue, $bits) {
284
		// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
285 View Code Duplication
		switch ($bits) {
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...
286
			case 32:
287
				$exponentbits = 8;
288
				$fractionbits = 23;
289
				break;
290
291
			case 64:
292
				$exponentbits = 11;
293
				$fractionbits = 52;
294
				break;
295
296
			default:
297
				return false;
298
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
299
		}
300
		if ($floatvalue >= 0) {
301
			$signbit = '0';
302
		} else {
303
			$signbit = '1';
304
		}
305
		$normalizedbinary  = NormalizeBinaryPoint(Float2BinaryDecimal($floatvalue), $fractionbits);
306
		$biasedexponent    = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent
307
		$exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits, '0', STR_PAD_LEFT);
308
		$fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2), $fractionbits, '0', STR_PAD_RIGHT);
309
310
		return BigEndian2String(Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
311
	}
312
}
313
314
if (!function_exists('LittleEndian2Float')) {
315
	function LittleEndian2Float($byteword) {
316
		return BigEndian2Float(strrev($byteword));
317
	}
318
}
319
320
if (!function_exists('BigEndian2Float')) {
321
	function BigEndian2Float($byteword) {
322
		// ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
323
		// http://www.psc.edu/general/software/packages/ieee/ieee.html
324
		// http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
325
326
		$bitword = BigEndian2Bin($byteword);
327
		$signbit = $bitword[0];
328
329
		switch (strlen($byteword) * 8) {
330
			case 32:
331
				$exponentbits = 8;
332
				$fractionbits = 23;
333
				break;
334
335
			case 64:
336
				$exponentbits = 11;
337
				$fractionbits = 52;
338
				break;
339
340
			case 80:
341
				$exponentbits = 16;
342
				$fractionbits = 64;
343
				break;
344
345
			default:
346
				return false;
347
				break;
0 ignored issues
show
Unused Code introduced by
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
348
		}
349
		$exponentstring = substr($bitword, 1, $exponentbits - 1);
350
		$fractionstring = substr($bitword, $exponentbits, $fractionbits);
351
		$exponent = Bin2Dec($exponentstring);
352
		$fraction = Bin2Dec($fractionstring);
353
354
		if (($exponentbits == 16) && ($fractionbits == 64)) {
355
			// 80-bit
356
			// As used in Apple AIFF for sample_rate
357
			// A bit of a hack, but it works ;)
358
			return pow(2, ($exponent  - 16382)) * DecimalBinary2Float($fractionstring);
359
		}
360
361
362 View Code Duplication
		if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) {
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...
363
			// Not a Number
364
			$floatvalue = false;
365
		} elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) {
366
			if ($signbit == '1') {
367
				$floatvalue = '-infinity';
368
			} else {
369
				$floatvalue = '+infinity';
370
			}
371
		} elseif (($exponent == 0) && ($fraction == 0)) {
372
			if ($signbit == '1') {
373
				$floatvalue = -0;
0 ignored issues
show
Unused Code introduced by
$floatvalue is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
374
			} else {
375
				$floatvalue = 0;
0 ignored issues
show
Unused Code introduced by
$floatvalue is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
376
			}
377
			$floatvalue = ($signbit ? 0 : -0);
378
		} elseif (($exponent == 0) && ($fraction != 0)) {
379
			// These are 'unnormalized' values
380
			$floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * DecimalBinary2Float($fractionstring);
381
			if ($signbit == '1') {
382
				$floatvalue *= -1;
383
			}
384
		} elseif ($exponent != 0) {
385
			$floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + DecimalBinary2Float($fractionstring));
386
			if ($signbit == '1') {
387
				$floatvalue *= -1;
388
			}
389
		}
390
		return (float) $floatvalue;
0 ignored issues
show
Bug introduced by
The variable $floatvalue does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
391
	}
392
}
393
394
if (!function_exists('BigEndian2Int')) {
395
	function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
396
		$intvalue = 0;
397
		$bytewordlen = strlen($byteword);
398 View Code Duplication
		for ($i = 0; $i < $bytewordlen; $i++) {
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...
399
			if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
400
				$intvalue = $intvalue | (ord($byteword[$i]) & 0x7F) << (($bytewordlen - 1 - $i) * 7);
401
			} else {
402
				$intvalue += ord($byteword[$i]) * pow(256, ($bytewordlen - 1 - $i));
403
			}
404
		}
405
		if ($signed && !$synchsafe) {
406
			// synchsafe ints are not allowed to be signed
407
			switch ($bytewordlen) {
408
				case 1:
409
				case 2:
410
				case 3:
411
				case 4:
412
					$signmaskbit = 0x80 << (8 * ($bytewordlen - 1));
413
					if ($intvalue & $signmaskbit) {
414
						$intvalue = 0 - ($intvalue & ($signmaskbit - 1));
415
					}
416
					break;
417
418
				default:
419
					die('ERROR: Cannot have signed integers larger than 32-bits in BigEndian2Int()');
420
					break;
0 ignored issues
show
Unused Code introduced by
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
421
			}
422
		}
423
		return CastAsInt($intvalue);
424
	}
425
}
426
427
if (!function_exists('LittleEndian2Int')) {
428
	function LittleEndian2Int($byteword, $signed=false) {
429
		return BigEndian2Int(strrev($byteword), false, $signed);
430
	}
431
}
432
433
if (!function_exists('BigEndian2Bin')) {
434 View Code Duplication
	function BigEndian2Bin($byteword) {
0 ignored issues
show
Duplication introduced by
This function 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...
435
		$binvalue = '';
436
		$bytewordlen = strlen($byteword);
437
		for ($i = 0; $i < $bytewordlen; $i++) {
438
			$binvalue .= str_pad(decbin(ord($byteword[$i])), 8, '0', STR_PAD_LEFT);
439
		}
440
		return $binvalue;
441
	}
442
}
443
444
if (!function_exists('BigEndian2String')) {
445
	function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
446
		if ($number < 0) {
447
			return false;
448
		}
449
		$maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF);
450
		$intstring = '';
451
		if ($signed) {
452
			if ($minbytes > 4) {
453
				die('ERROR: Cannot have signed integers larger than 32-bits in BigEndian2String()');
454
			}
455
			$number = $number & (0x80 << (8 * ($minbytes - 1)));
456
		}
457 View Code Duplication
		while ($number != 0) {
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...
458
			$quotient = ($number / ($maskbyte + 1));
459
			$intstring = chr(ceil(($quotient - floor($quotient)) * $maskbyte)).$intstring;
460
			$number = floor($quotient);
461
		}
462
		return str_pad($intstring, $minbytes, chr(0), STR_PAD_LEFT);
463
	}
464
}
465
466
if (!function_exists('Dec2Bin')) {
467 View Code Duplication
	function Dec2Bin($number) {
0 ignored issues
show
Duplication introduced by
This function 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...
468
		while ($number >= 256) {
469
			$bytes[] = (($number / 256) - (floor($number / 256))) * 256;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$bytes was never initialized. Although not strictly required by PHP, it is generally a good practice to add $bytes = 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...
470
			$number = floor($number / 256);
471
		}
472
		$bytes[] = $number;
0 ignored issues
show
Bug introduced by
The variable $bytes does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
473
		$binstring = '';
474
		for ($i = 0; $i < count($bytes); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
475
			$binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, '0', STR_PAD_LEFT)).$binstring;
476
		}
477
		return $binstring;
478
	}
479
}
480
481
if (!function_exists('Bin2Dec')) {
482
	function Bin2Dec($binstring) {
483
		$decvalue = 0;
484 View Code Duplication
		for ($i = 0; $i < strlen($binstring); $i++) {
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...
485
			$decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
486
		}
487
		return CastAsInt($decvalue);
488
	}
489
}
490
491
if (!function_exists('Bin2String')) {
492 View Code Duplication
	function Bin2String($binstring) {
0 ignored issues
show
Duplication introduced by
This function 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...
493
		// return 'hi' for input of '0110100001101001'
494
		$string = '';
495
		$binstringreversed = strrev($binstring);
496
		for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
497
			$string = chr(Bin2Dec(strrev(substr($binstringreversed, $i, 8)))).$string;
498
		}
499
		return $string;
500
	}
501
}
502
503
if (!function_exists('LittleEndian2String')) {
504 View Code Duplication
	function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
0 ignored issues
show
Duplication introduced by
This function 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...
505
		$intstring = '';
506
		while ($number > 0) {
507
			if ($synchsafe) {
508
				$intstring = $intstring.chr($number & 127);
509
				$number >>= 7;
510
			} else {
511
				$intstring = $intstring.chr($number & 255);
512
				$number >>= 8;
513
			}
514
		}
515
		return str_pad($intstring, $minbytes, chr(0), STR_PAD_RIGHT);
516
	}
517
}
518
519
if (!function_exists('Bool2IntString')) {
520
	function Bool2IntString($intvalue) {
521
		return ($intvalue ? '1' : '0');
522
	}
523
}
524
525
if (!function_exists('IntString2Bool')) {
526 View Code Duplication
	function IntString2Bool($char) {
0 ignored issues
show
Duplication introduced by
This function 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...
527
		if ($char == '1') {
528
			return true;
529
		} elseif ($char == '0') {
530
			return false;
531
		}
532
		return null;
533
	}
534
}
535
536
if (!function_exists('InverseBoolean')) {
537
	function InverseBoolean($value) {
538
		return ($value ? false : true);
539
	}
540
}
541
542
if (!function_exists('DeUnSynchronise')) {
543
	function DeUnSynchronise($data) {
544
		return str_replace(chr(0xFF).chr(0x00), chr(0xFF), $data);
545
	}
546
}
547
548
if (!function_exists('Unsynchronise')) {
549
	function Unsynchronise($data) {
550
		// Whenever a false synchronisation is found within the tag, one zeroed
551
		// byte is inserted after the first false synchronisation byte. The
552
		// format of a correct sync that should be altered by ID3 encoders is as
553
		// follows:
554
		//      %11111111 111xxxxx
555
		// And should be replaced with:
556
		//      %11111111 00000000 111xxxxx
557
		// This has the side effect that all $FF 00 combinations have to be
558
		// altered, so they won't be affected by the decoding process. Therefore
559
		// all the $FF 00 combinations have to be replaced with the $FF 00 00
560
		// combination during the unsynchronisation.
561
562
		$data = str_replace(chr(0xFF).chr(0x00), chr(0xFF).chr(0x00).chr(0x00), $data);
563
		$unsyncheddata = '';
564
		for ($i = 0; $i < strlen($data); $i++) {
565
			$thischar = $data[$i];
566
			$unsyncheddata .= $thischar;
567
			if ($thischar == chr(255)) {
568
				$nextchar = ord(substr($data, $i + 1, 1));
569
				if (($nextchar | 0xE0) == 0xE0) {
570
					// previous byte = 11111111, this byte = 111?????
571
					$unsyncheddata .= chr(0);
572
				}
573
			}
574
		}
575
		return $unsyncheddata;
576
	}
577
}
578
579
if (!function_exists('is_hash')) {
580 View Code Duplication
	function is_hash($var) {
0 ignored issues
show
Duplication introduced by
This function 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...
581
		// written by [email protected]
582
		// taken from http://www.php.net/manual/en/function.array-merge-recursive.php
583
		if (is_array($var)) {
584
			$keys = array_keys($var);
585
			$all_num = true;
0 ignored issues
show
Unused Code introduced by
$all_num is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
586
			for ($i = 0; $i < count($keys); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
587
				if (is_string($keys[$i])) {
588
					return true;
589
				}
590
			}
591
		}
592
		return false;
593
	}
594
}
595
596
if (!function_exists('array_join_merge')) {
597
	function array_join_merge($arr1, $arr2) {
598
		// written by [email protected]
599
		// taken from http://www.php.net/manual/en/function.array-merge-recursive.php
600
		if (is_array($arr1) && is_array($arr2)) {
601
			// the same -> merge
602
			$new_array = array();
603
604
			if (is_hash($arr1) && is_hash($arr2)) {
605
				// hashes -> merge based on keys
606
				$keys = array_merge(array_keys($arr1), array_keys($arr2));
607
				foreach ($keys as $key) {
608
					$arr1[$key] = (isset($arr1[$key]) ? $arr1[$key] : '');
609
					$arr2[$key] = (isset($arr2[$key]) ? $arr2[$key] : '');
610
					$new_array[$key] = array_join_merge($arr1[$key], $arr2[$key]);
611
				}
612
			} else {
613
				// two real arrays -> merge
614
				$new_array = array_reverse(array_unique(array_reverse(array_merge($arr1,$arr2))));
615
			}
616
			return $new_array;
617
		} else {
618
			// not the same ... take new one if defined, else the old one stays
619
			return $arr2 ? $arr2 : $arr1;
620
		}
621
	}
622
}
623
624 View Code Duplication
if (!function_exists('array_merge_clobber')) {
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...
625
	function array_merge_clobber($array1, $array2) {
626
		// written by [email protected]
627
		// taken from http://www.php.net/manual/en/function.array-merge-recursive.php
628
		if (!is_array($array1) || !is_array($array2)) {
629
			return false;
630
		}
631
		$newarray = $array1;
632
		foreach ($array2 as $key => $val) {
633
			if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
634
				$newarray[$key] = array_merge_clobber($newarray[$key], $val);
635
			} else {
636
				$newarray[$key] = $val;
637
			}
638
		}
639
		return $newarray;
640
	}
641
}
642
643 View Code Duplication
if (!function_exists('array_merge_noclobber')) {
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...
644
	function array_merge_noclobber($array1, $array2) {
645
		if (!is_array($array1) || !is_array($array2)) {
646
			return false;
647
		}
648
		$newarray = $array1;
649
		foreach ($array2 as $key => $val) {
650
			if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
651
				$newarray[$key] = array_merge_noclobber($newarray[$key], $val);
652
			} elseif (!isset($newarray[$key])) {
653
				$newarray[$key] = $val;
654
			}
655
		}
656
		return $newarray;
657
	}
658
}
659
660
if (!function_exists('RoughTranslateUnicodeToASCII')) {
661
	function RoughTranslateUnicodeToASCII($rawdata, $frame_textencoding) {
662
		// rough translation of data for application that can't handle Unicode data
663
664
		$tempstring = '';
665
		switch ($frame_textencoding) {
666
			case 0: // ISO-8859-1. Terminated with $00.
667
				$asciidata = $rawdata;
668
				break;
669
670
			case 1: // UTF-16 encoded Unicode with BOM. Terminated with $00 00.
671
				$asciidata = $rawdata;
672
				if (substr($asciidata, 0, 2) == chr(0xFF).chr(0xFE)) {
673
					// remove BOM, only if present (it should be, but...)
674
					$asciidata = substr($asciidata, 2);
675
				}
676
				if (substr($asciidata, strlen($asciidata) - 2, 2) == chr(0).chr(0)) {
677
					$asciidata = substr($asciidata, 0, strlen($asciidata) - 2); // remove terminator, only if present (it should be, but...)
678
				}
679 View Code Duplication
				for ($i = 0; $i < strlen($asciidata); $i += 2) {
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...
680
					if ((ord($asciidata[$i]) <= 0x7F) || (ord($asciidata[$i]) >= 0xA0)) {
681
						$tempstring .= $asciidata[$i];
682
					} else {
683
						$tempstring .= '?';
684
					}
685
				}
686
				$asciidata = $tempstring;
687
				break;
688
689
			case 2: // UTF-16BE encoded Unicode without BOM. Terminated with $00 00.
690
				$asciidata = $rawdata;
691
				if (substr($asciidata, strlen($asciidata) - 2, 2) == chr(0).chr(0)) {
692
					$asciidata = substr($asciidata, 0, strlen($asciidata) - 2); // remove terminator, only if present (it should be, but...)
693
				}
694 View Code Duplication
				for ($i = 0; $i < strlen($asciidata); $i += 2) {
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...
695
					if ((ord($asciidata[$i]) <= 0x7F) || (ord($asciidata[$i]) >= 0xA0)) {
696
						$tempstring .= $asciidata[$i];
697
					} else {
698
						$tempstring .= '?';
699
					}
700
				}
701
				$asciidata = $tempstring;
702
				break;
703
704
			case 3: // UTF-8 encoded Unicode. Terminated with $00.
705
				$asciidata = utf8_decode($rawdata);
706
				break;
707
708
			case 255: // Unicode, Big-Endian. Terminated with $00 00.
709
				$asciidata = $rawdata;
710
				if (substr($asciidata, strlen($asciidata) - 2, 2) == chr(0).chr(0)) {
711
					$asciidata = substr($asciidata, 0, strlen($asciidata) - 2); // remove terminator, only if present (it should be, but...)
712
				}
713
				for ($i = 0; ($i + 1) < strlen($asciidata); $i += 2) {
714
					if ((ord($asciidata[($i + 1)]) <= 0x7F) || (ord($asciidata[($i + 1)]) >= 0xA0)) {
715
						$tempstring .= $asciidata[($i + 1)];
716
					} else {
717
						$tempstring .= '?';
718
					}
719
				}
720
				$asciidata = $tempstring;
721
				break;
722
723
724
			default:
725
				// shouldn't happen, but in case $frame_textencoding is not 1 <= $frame_textencoding <= 4
726
				// just pass the data through unchanged.
727
				$asciidata = $rawdata;
728
				break;
729
		}
730
		if (substr($asciidata, strlen($asciidata) - 1, 1) == chr(0)) {
731
			// remove null terminator, if present
732
			$asciidata = NoNullString($asciidata);
733
		}
734
		return $asciidata;
735
		// return str_replace(chr(0), '', $asciidata); // just in case any nulls slipped through
736
	}
737
}
738
739
if (!function_exists('PlaytimeString')) {
740
	function PlaytimeString($playtimeseconds) {
741
		$contentseconds = round((($playtimeseconds / 60) - floor($playtimeseconds / 60)) * 60);
742
		$contentminutes = floor($playtimeseconds / 60);
743
		if ($contentseconds >= 60) {
744
			$contentseconds -= 60;
745
			$contentminutes++;
746
		}
747
		return number_format($contentminutes).':'.str_pad($contentseconds, 2, 0, STR_PAD_LEFT);
748
	}
749
}
750
751
if (!function_exists('CloseMatch')) {
752
	function CloseMatch($value1, $value2, $tolerance) {
753
		return (abs($value1 - $value2) <= $tolerance);
754
	}
755
}
756
757
if (!function_exists('ID3v1matchesID3v2')) {
758
	function ID3v1matchesID3v2($id3v1, $id3v2) {
759
760
		$requiredindices = array('title', 'artist', 'album', 'year', 'genre', 'comment');
761
		foreach ($requiredindices as $requiredindex) {
762
			if (!isset($id3v1["$requiredindex"])) {
763
				$id3v1["$requiredindex"] = '';
764
			}
765
			if (!isset($id3v2["$requiredindex"])) {
766
				$id3v2["$requiredindex"] = '';
767
			}
768
		}
769
770
		if (trim($id3v1['title']) != trim(substr($id3v2['title'], 0, 30))) {
771
			return false;
772
		}
773
		if (trim($id3v1['artist']) != trim(substr($id3v2['artist'], 0, 30))) {
774
			return false;
775
		}
776
		if (trim($id3v1['album']) != trim(substr($id3v2['album'], 0, 30))) {
777
			return false;
778
		}
779 View Code Duplication
		if (trim($id3v1['year']) != trim(substr($id3v2['year'], 0, 4))) {
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...
780
			return false;
781
		}
782
		if (trim($id3v1['genre']) != trim($id3v2['genre'])) {
783
			return false;
784
		}
785
		if (isset($id3v1['track_number'])) {
786
			if (!isset($id3v1['track_number']) || (trim($id3v1['track_number']) != trim($id3v2['track_number']))) {
787
				return false;
788
			}
789 View Code Duplication
			if (trim($id3v1['comment']) != trim(substr($id3v2['comment'], 0, 28))) {
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...
790
				return false;
791
			}
792 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...
793
			if (trim($id3v1['comment']) != trim(substr($id3v2['comment'], 0, 30))) {
794
				return false;
795
			}
796
		}
797
		return true;
798
	}
799
}
800
801
if (!function_exists('FILETIMEtoUNIXtime')) {
802
	function FILETIMEtoUNIXtime($FILETIME, $round=true) {
803
		// FILETIME is a 64-bit unsigned integer representing
804
		// the number of 100-nanosecond intervals since January 1, 1601
805
		// UNIX timestamp is number of seconds since January 1, 1970
806
		// 116444736000000000 = 10000000 * 60 * 60 * 24 * 365 * 369 + 89 leap days
807
		if ($round) {
808
			return round(($FILETIME - 116444736000000000) / 10000000);
809
		}
810
		return ($FILETIME - 116444736000000000) / 10000000;
811
	}
812
}
813
814
if (!function_exists('GUIDtoBytestring')) {
815 View Code Duplication
	function GUIDtoBytestring($GUIDstring) {
0 ignored issues
show
Duplication introduced by
This function 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...
816
		// Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way:
817
		// first 4 bytes are in little-endian order
818
		// next 2 bytes are appended in little-endian order
819
		// next 2 bytes are appended in little-endian order
820
		// next 2 bytes are appended in big-endian order
821
		// next 6 bytes are appended in big-endian order
822
823
		// AaBbCcDd-EeFf-GgHh-IiJj-KkLlMmNnOoPp is stored as this 16-byte string:
824
		// $Dd $Cc $Bb $Aa $Ff $Ee $Hh $Gg $Ii $Jj $Kk $Ll $Mm $Nn $Oo $Pp
825
826
		$hexbytecharstring  = chr(hexdec(substr($GUIDstring,  6, 2)));
827
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring,  4, 2)));
828
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring,  2, 2)));
829
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring,  0, 2)));
830
831
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 11, 2)));
832
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring,  9, 2)));
833
834
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 16, 2)));
835
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 14, 2)));
836
837
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 19, 2)));
838
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 21, 2)));
839
840
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 24, 2)));
841
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 26, 2)));
842
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 28, 2)));
843
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 30, 2)));
844
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 32, 2)));
845
		$hexbytecharstring .= chr(hexdec(substr($GUIDstring, 34, 2)));
846
847
		return $hexbytecharstring;
848
	}
849
}
850
851
if (!function_exists('BytestringToGUID')) {
852 View Code Duplication
	function BytestringToGUID($Bytestring) {
0 ignored issues
show
Duplication introduced by
This function 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...
853
		$GUIDstring  = str_pad(dechex(ord($Bytestring[3])),  2, '0', STR_PAD_LEFT);
854
		$GUIDstring .= str_pad(dechex(ord($Bytestring[2])),  2, '0', STR_PAD_LEFT);
855
		$GUIDstring .= str_pad(dechex(ord($Bytestring[1])),  2, '0', STR_PAD_LEFT);
856
		$GUIDstring .= str_pad(dechex(ord($Bytestring[0])),  2, '0', STR_PAD_LEFT);
857
		$GUIDstring .= '-';
858
		$GUIDstring .= str_pad(dechex(ord($Bytestring[5])),  2, '0', STR_PAD_LEFT);
859
		$GUIDstring .= str_pad(dechex(ord($Bytestring[4])),  2, '0', STR_PAD_LEFT);
860
		$GUIDstring .= '-';
861
		$GUIDstring .= str_pad(dechex(ord($Bytestring[7])),  2, '0', STR_PAD_LEFT);
862
		$GUIDstring .= str_pad(dechex(ord($Bytestring[6])),  2, '0', STR_PAD_LEFT);
863
		$GUIDstring .= '-';
864
		$GUIDstring .= str_pad(dechex(ord($Bytestring[8])),  2, '0', STR_PAD_LEFT);
865
		$GUIDstring .= str_pad(dechex(ord($Bytestring[9])),  2, '0', STR_PAD_LEFT);
866
		$GUIDstring .= '-';
867
		$GUIDstring .= str_pad(dechex(ord($Bytestring[10])), 2, '0', STR_PAD_LEFT);
868
		$GUIDstring .= str_pad(dechex(ord($Bytestring[11])), 2, '0', STR_PAD_LEFT);
869
		$GUIDstring .= str_pad(dechex(ord($Bytestring[12])), 2, '0', STR_PAD_LEFT);
870
		$GUIDstring .= str_pad(dechex(ord($Bytestring[13])), 2, '0', STR_PAD_LEFT);
871
		$GUIDstring .= str_pad(dechex(ord($Bytestring[14])), 2, '0', STR_PAD_LEFT);
872
		$GUIDstring .= str_pad(dechex(ord($Bytestring[15])), 2, '0', STR_PAD_LEFT);
873
874
		return strtoupper($GUIDstring);
875
	}
876
}
877
878
if (!function_exists('BitrateColor')) {
879 View Code Duplication
	function BitrateColor($bitrate) {
0 ignored issues
show
Duplication introduced by
This function 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...
Best Practice introduced by
The function BitrateColor() has been defined more than once; this definition is ignored, only the first definition in 3rdparty/getID3/demos/demo.browse.php (L426-442) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
880
		$bitrate /= 3; // scale from 1-768kbps to 1-256kbps
881
		$bitrate--;    // scale from 1-256kbps to 0-255kbps
882
		$bitrate = max($bitrate, 0);
883
		$bitrate = min($bitrate, 255);
884
		//$bitrate = max($bitrate, 32);
885
		//$bitrate = min($bitrate, 143);
886
		//$bitrate = ($bitrate * 2) - 32;
887
888
		$Rcomponent = max(255 - ($bitrate * 2), 0);
889
		$Gcomponent = max(($bitrate * 2) - 255, 0);
890
		if ($bitrate > 127) {
891
			$Bcomponent = max((255 - $bitrate) * 2, 0);
892
		} else {
893
			$Bcomponent = max($bitrate * 2, 0);
894
		}
895
		return str_pad(dechex($Rcomponent), 2, '0', STR_PAD_LEFT).str_pad(dechex($Gcomponent), 2, '0', STR_PAD_LEFT).str_pad(dechex($Bcomponent), 2, '0', STR_PAD_LEFT);
896
	}
897
}
898
899
if (!function_exists('BitrateText')) {
900
	function BitrateText($bitrate) {
0 ignored issues
show
Best Practice introduced by
The function BitrateText() has been defined more than once; this definition is ignored, only the first definition in 3rdparty/getID3/demos/demo.browse.php (L444-446) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
901
		return '<SPAN STYLE="color: #'.BitrateColor($bitrate).'">'.round($bitrate).' kbps</SPAN>';
902
	}
903
}
904
905
if (!function_exists('image_type_to_mime_type')) {
906
	function image_type_to_mime_type($imagetypeid) {
907
		// only available in PHP v4.3.0+
908
		static $image_type_to_mime_type = array();
909
		if (empty($image_type_to_mime_type)) {
910
			$image_type_to_mime_type[1]  = 'image/gif';                     // GIF
911
			$image_type_to_mime_type[2]  = 'image/jpeg';                    // JPEG
912
			$image_type_to_mime_type[3]  = 'image/png';                     // PNG
913
			$image_type_to_mime_type[4]  = 'application/x-shockwave-flash'; // Flash
914
			$image_type_to_mime_type[5]  = 'image/psd';                     // PSD
915
			$image_type_to_mime_type[6]  = 'image/bmp';                     // BMP
916
			$image_type_to_mime_type[7]  = 'image/tiff';                    // TIFF: little-endian (Intel)
917
			$image_type_to_mime_type[8]  = 'image/tiff';                    // TIFF: big-endian (Motorola)
918
			//$image_type_to_mime_type[9]  = 'image/jpc';                   // JPC
919
			//$image_type_to_mime_type[10] = 'image/jp2';                   // JPC
920
			//$image_type_to_mime_type[11] = 'image/jpx';                   // JPC
921
			//$image_type_to_mime_type[12] = 'image/jb2';                   // JPC
922
			$image_type_to_mime_type[13] = 'application/x-shockwave-flash'; // Shockwave
923
			$image_type_to_mime_type[14] = 'image/iff';                     // IFF
924
		}
925
		return (isset($image_type_to_mime_type[$imagetypeid]) ? $image_type_to_mime_type[$imagetypeid] : 'application/octet-stream');
926
	}
927
}
928
929
if (!function_exists('utf8_decode')) {
930
	// PHP has this function built-in if it's configured with the --with-xml option
931
	// This version of the function is only provided in case XML isn't installed
932
	function utf8_decode($utf8text) {
933
		// http://www.php.net/manual/en/function.utf8-encode.php
934
		// bytes  bits  representation
935
		//   1     7    0bbbbbbb
936
		//   2     11   110bbbbb 10bbbbbb
937
		//   3     16   1110bbbb 10bbbbbb 10bbbbbb
938
		//   4     21   11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
939
940
		$utf8length = strlen($utf8text);
941
		$decodedtext = '';
942
		for ($i = 0; $i < $utf8length; $i++) {
943
			if ((ord($utf8text[$i]) & 0x80) == 0) {
944
				$decodedtext .= $utf8text[$i];
945
			} elseif ((ord($utf8text[$i]) & 0xF0) == 0xF0) {
946
				$decodedtext .= '?';
947
				$i += 3;
948
			} elseif ((ord($utf8text[$i]) & 0xE0) == 0xE0) {
949
				$decodedtext .= '?';
950
				$i += 2;
951
			} elseif ((ord($utf8text[$i]) & 0xC0) == 0xC0) {
952
				//   2     11   110bbbbb 10bbbbbb
953
				$decodedchar = Bin2Dec(substr(Dec2Bin(ord($utf8text[$i])), 3, 5).substr(Dec2Bin(ord($utf8text[($i + 1)])), 2, 6));
954
				if ($decodedchar <= 255) {
955
					$decodedtext .= chr($decodedchar);
956
				} else {
957
					$decodedtext .= '?';
958
				}
959
				$i += 1;
960
			}
961
		}
962
		return $decodedtext;
963
	}
964
}
965
966
if (!function_exists('DateMac2Unix')) {
967
	function DateMac2Unix($macdate) {
968
		// Macintosh timestamp: seconds since 00:00h January 1, 1904
969
		// UNIX timestamp:      seconds since 00:00h January 1, 1970
970
		return CastAsInt($macdate - 2082844800);
971
	}
972
}
973
974
975 View Code Duplication
if (!function_exists('FixedPoint8_8')) {
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...
976
	function FixedPoint8_8($rawdata) {
977
		return BigEndian2Int(substr($rawdata, 0, 1)) + (float) (BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
978
	}
979
}
980
981
982 View Code Duplication
if (!function_exists('FixedPoint16_16')) {
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...
983
	function FixedPoint16_16($rawdata) {
984
		return BigEndian2Int(substr($rawdata, 0, 2)) + (float) (BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
985
	}
986
}
987
988
989
if (!function_exists('FixedPoint2_30')) {
990
	function FixedPoint2_30($rawdata) {
991
		$binarystring = BigEndian2Bin($rawdata);
992
		return Bin2Dec(substr($binarystring, 0, 2)) + (float) (Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
993
	}
994
}
995
996
997
if (!function_exists('Pascal2String')) {
998
	function Pascal2String($pascalstring) {
999
		// Pascal strings have 1 byte at the beginning saying how many chars are in the string
1000
		return substr($pascalstring, 1);
1001
	}
1002
}
1003
1004
if (!function_exists('NoNullString')) {
1005 View Code Duplication
	function NoNullString($nullterminatedstring) {
0 ignored issues
show
Duplication introduced by
This function 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...
1006
		// remove the single null terminator on null terminated strings
1007
		if (substr($nullterminatedstring, strlen($nullterminatedstring) - 1, 1) === chr(0)) {
1008
			return substr($nullterminatedstring, 0, strlen($nullterminatedstring) - 1);
1009
		}
1010
		return $nullterminatedstring;
1011
	}
1012
}
1013
1014
if (!function_exists('FileSizeNiceDisplay')) {
1015
	function FileSizeNiceDisplay($filesize, $precision=2) {
1016
		if ($filesize < 1000) {
1017
			$sizeunit  = 'bytes';
1018
			$precision = 0;
1019
		} else {
1020
			$filesize /= 1024;
1021
			$sizeunit = 'kB';
1022
		}
1023
		if ($filesize >= 1000) {
1024
			$filesize /= 1024;
1025
			$sizeunit = 'MB';
1026
		}
1027
		if ($filesize >= 1000) {
1028
			$filesize /= 1024;
1029
			$sizeunit = 'GB';
1030
		}
1031
		return number_format($filesize, $precision).' '.$sizeunit;
1032
	}
1033
}
1034
1035
if (!function_exists('DOStime2UNIXtime')) {
1036 View Code Duplication
	function DOStime2UNIXtime($DOSdate, $DOStime) {
0 ignored issues
show
Duplication introduced by
This function 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...
1037
		// wFatDate
1038
		// Specifies the MS-DOS date. The date is a packed 16-bit value with the following format:
1039
		// Bits      Contents
1040
		// 0-4    Day of the month (1-31)
1041
		// 5-8    Month (1 = January, 2 = February, and so on)
1042
		// 9-15   Year offset from 1980 (add 1980 to get actual year)
1043
1044
		$UNIXday    =  ($DOSdate & 0x001F);
1045
		$UNIXmonth  = (($DOSdate & 0x01E0) >> 5);
1046
		$UNIXyear   = (($DOSdate & 0xFE00) >> 9) + 1980;
1047
1048
		// wFatTime
1049
		// Specifies the MS-DOS time. The time is a packed 16-bit value with the following format:
1050
		// Bits   Contents
1051
		// 0-4    Second divided by 2
1052
		// 5-10   Minute (0-59)
1053
		// 11-15  Hour (0-23 on a 24-hour clock)
1054
1055
		$UNIXsecond =  ($DOStime & 0x001F) * 2;
1056
		$UNIXminute = (($DOStime & 0x07E0) >> 5);
1057
		$UNIXhour   = (($DOStime & 0xF800) >> 11);
1058
1059
		return mktime($UNIXhour, $UNIXminute, $UNIXsecond, $UNIXmonth, $UNIXday, $UNIXyear);
1060
	}
1061
}
1062
1063
if (!function_exists('CreateDeepArray')) {
1064
	function CreateDeepArray($ArrayPath, $Separator, $Value) {
1065
		// assigns $Value to a nested array path:
1066
		//   $foo = CreateDeepArray('/path/to/my', '/', 'file.txt')
1067
		// is the same as:
1068
		//   $foo = array('path'=>array('to'=>'array('my'=>array('file.txt'))));
1069
		// or
1070
		//   $foo['path']['to']['my'] = 'file.txt';
1071
		while ($ArrayPath[0] == $Separator) {
1072
			$ArrayPath = substr($ArrayPath, 1);
1073
		}
1074 View Code Duplication
		if (($pos = strpos($ArrayPath, $Separator)) !== false) {
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...
1075
			$ReturnedArray[substr($ArrayPath, 0, $pos)] = CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ReturnedArray was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ReturnedArray = 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...
1076
		} else {
1077
			$ReturnedArray["$ArrayPath"] = $Value;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$ReturnedArray was never initialized. Although not strictly required by PHP, it is generally a good practice to add $ReturnedArray = 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...
1078
		}
1079
		return $ReturnedArray;
1080
	}
1081
}
1082
1083
if (!function_exists('md5_data')) {
1084
	// Allan Hansen <[email protected]>
1085
	// md5_data() - returns md5sum for a file from startuing position to absolute end position
1086
1087
	function md5_data($file, $offset, $end, $invertsign=false) {
1088
		// first try and create a temporary file in the same directory as the file being scanned
1089
		if (($dataMD5filename = tempnam(dirname($file), preg_replace('#[^[:alnum:]]#i', '', basename($file)))) === false) {
1090
			// if that fails, create a temporary file in the system temp directory
1091
			if (($dataMD5filename = tempnam('/tmp', 'getID3')) === false) {
1092
				// if that fails, create a temporary file in the current directory
1093
				if (($dataMD5filename = tempnam('.', preg_replace('#[^[:alnum:]]#i', '', basename($file)))) === false) {
1094
					// can't find anywhere to create a temp file, just die
1095
					return false;
1096
				}
1097
			}
1098
		}
1099
		$md5 = false;
1100
		set_time_limit(max(filesize($file) / 1000000, 30));
1101
1102
		// copy parts of file
1103
		ob_start();
1104
		if ($fp = fopen($file, 'rb')) {
1105
			ob_end_clean();
1106
1107
			ob_start();
1108
			if ($MD5fp = fopen($dataMD5filename, 'wb')) {
1109
1110
				ob_end_clean();
1111
				if ($invertsign) {
1112
					// Load conversion lookup strings for 8-bit unsigned->signed conversion below
1113
					$from = '';
1114
					$to   = '';
1115 View Code Duplication
					for ($i = 0; $i < 128; $i++) {
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...
1116
						$from .= chr($i);
1117
						$to   .= chr($i + 128);
1118
					}
1119 View Code Duplication
					for ($i = 128; $i < 256; $i++) {
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...
1120
						$from .= chr($i);
1121
						$to   .= chr($i - 128);
1122
					}
1123
				}
1124
1125
				fseek($fp, $offset, SEEK_SET);
1126
				$byteslefttowrite = $end - $offset;
1127
				while (($byteslefttowrite > 0) && ($buffer = fread($fp, 32768))) {
1128
					if ($invertsign) {
1129
						// Possibly FLAC-specific (?)
1130
						// FLAC calculates the MD5sum of the source data of 8-bit files
1131
						// not on the actual byte values in the source file, but of those
1132
						// values converted from unsigned to signed, or more specifcally,
1133
						// with the MSB inverted. ex: 01 -> 81; F5 -> 75; etc
1134
1135
						// Therefore, 8-bit WAV data has to be converted before getting the
1136
						// md5_data value so as to match the FLAC value
1137
1138
						// Flip the MSB for each byte in the buffer before copying
1139
						$buffer = strtr($buffer, $from, $to);
0 ignored issues
show
Bug introduced by
The variable $from does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
Bug introduced by
The variable $to does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
1140
					}
1141
					$byteswritten = fwrite($MD5fp, $buffer, $byteslefttowrite);
1142
					$byteslefttowrite -= $byteswritten;
1143
				}
1144
				fclose($MD5fp);
1145
				$md5 = md5_file($dataMD5filename);
1146
1147
			} else {
1148
				$errormessage = ob_get_contents();
0 ignored issues
show
Unused Code introduced by
$errormessage is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1149
				ob_end_clean();
1150
			}
1151
			fclose($fp);
1152
1153
		} else {
1154
			$errormessage = ob_get_contents();
0 ignored issues
show
Unused Code introduced by
$errormessage is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1155
			ob_end_clean();
1156
		}
1157
		unlink($dataMD5filename);
1158
		return $md5;
1159
	}
1160
}
1161
1162
if (!function_exists('TwosCompliment2Decimal')) {
1163
	function TwosCompliment2Decimal($BinaryValue) {
1164
		// http://sandbox.mc.edu/~bennet/cs110/tc/tctod.html
1165
		// First check if the number is negative or positive by looking at the sign bit.
1166
		// If it is positive, simply convert it to decimal.
1167
		// If it is negative, make it positive by inverting the bits and adding one.
1168
		// Then, convert the result to decimal.
1169
		// The negative of this number is the value of the original binary.
1170
1171 View Code Duplication
		if ($BinaryValue & 0x80) {
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...
1172
1173
			// negative number
1174
			return (0 - ((~$BinaryValue & 0xFF) + 1));
1175
1176
		} else {
1177
1178
			// positive number
1179
			return $BinaryValue;
1180
1181
		}
1182
1183
	}
1184
}
1185
1186
if (!function_exists('LastArrayElement')) {
1187
	function LastArrayElement($MyArray) {
1188
		if (!is_array($MyArray)) {
1189
			return false;
1190
		}
1191
		if (empty($MyArray)) {
1192
			return null;
1193
		}
1194
		foreach ($MyArray as $key => $value) {
1195
		}
1196
		return $value;
0 ignored issues
show
Bug introduced by
The variable $value seems to be defined by a foreach iteration on line 1194. Are you sure the iterator is never empty, otherwise this variable is not defined?

It seems like you are relying on a variable being defined by an iteration:

foreach ($a as $b) {
}

// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.


// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}

// $b is now guaranteed to be defined here.
Loading history...
1197
	}
1198
}
1199
1200
if (!function_exists('safe_inc')) {
1201
	function safe_inc(&$variable, $increment=1) {
1202
		if (isset($variable)) {
1203
			$variable += $increment;
1204
		} else {
1205
			$variable = $increment;
1206
		}
1207
		return true;
1208
	}
1209
}
1210
1211
if (!function_exists('CalculateCompressionRatioVideo')) {
1212
	function CalculateCompressionRatioVideo(&$ThisFileInfo) {
1213
		if (empty($ThisFileInfo['video'])) {
1214
			return false;
1215
		}
1216
		if (empty($ThisFileInfo['video']['resolution_x']) || empty($ThisFileInfo['video']['resolution_y'])) {
1217
			return false;
1218
		}
1219
		if (empty($ThisFileInfo['video']['bits_per_sample'])) {
1220
			return false;
1221
		}
1222
1223
		switch ($ThisFileInfo['video']['dataformat']) {
1224
			case 'bmp':
1225
			case 'gif':
1226
			case 'jpeg':
1227
			case 'jpg':
1228
			case 'png':
1229 View Code Duplication
			case 'tiff':
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...
1230
				$FrameRate = 1;
1231
				$PlaytimeSeconds = 1;
0 ignored issues
show
Unused Code introduced by
$PlaytimeSeconds is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1232
				$BitrateCompressed = $ThisFileInfo['filesize'] * 8;
1233
				break;
1234
1235
			default:
1236
				if (!empty($ThisFileInfo['video']['frame_rate'])) {
1237
					$FrameRate = $ThisFileInfo['video']['frame_rate'];
1238
				} else {
1239
					return false;
1240
				}
1241
				if (!empty($ThisFileInfo['playtime_seconds'])) {
1242
					$PlaytimeSeconds = $ThisFileInfo['playtime_seconds'];
0 ignored issues
show
Unused Code introduced by
$PlaytimeSeconds is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1243
				} else {
1244
					return false;
1245
				}
1246
				if (!empty($ThisFileInfo['video']['bitrate'])) {
1247
					$BitrateCompressed = $ThisFileInfo['video']['bitrate'];
1248
				} else {
1249
					return false;
1250
				}
1251
				break;
1252
		}
1253
		$BitrateUncompressed = $ThisFileInfo['video']['resolution_x'] * $ThisFileInfo['video']['resolution_y'] * $ThisFileInfo['video']['bits_per_sample'] * $FrameRate;
1254
1255
		$ThisFileInfo['video']['compression_ratio'] = $BitrateCompressed / $BitrateUncompressed;
1256
		return true;
1257
	}
1258
}
1259
1260
if (!function_exists('CalculateCompressionRatioAudio')) {
1261
	function CalculateCompressionRatioAudio(&$ThisFileInfo) {
1262
		if (empty($ThisFileInfo['audio']['bitrate']) || empty($ThisFileInfo['audio']['channels']) || empty($ThisFileInfo['audio']['sample_rate']) || empty($ThisFileInfo['audio']['bits_per_sample'])) {
1263
			return false;
1264
		}
1265
		$ThisFileInfo['audio']['compression_ratio'] = $ThisFileInfo['audio']['bitrate'] / ($ThisFileInfo['audio']['channels'] * $ThisFileInfo['audio']['sample_rate'] * $ThisFileInfo['audio']['bits_per_sample']);
1266
		return true;
1267
	}
1268
}
1269
1270
if (!function_exists('IsValidMIMEstring')) {
1271
	function IsValidMIMEstring($mimestring) {
1272
		if ((strlen($mimestring) >= 3) && (strpos($mimestring, '/') > 0) && (strpos($mimestring, '/') < (strlen($mimestring) - 1))) {
1273
			return true;
1274
		}
1275
		return false;
1276
	}
1277
}
1278
1279
if (!function_exists('IsWithinBitRange')) {
1280 View Code Duplication
	function IsWithinBitRange($number, $maxbits, $signed=false) {
0 ignored issues
show
Duplication introduced by
This function 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...
1281
		if ($signed) {
1282
			if (($number > (0 - pow(2, $maxbits - 1))) && ($number <= pow(2, $maxbits - 1))) {
1283
				return true;
1284
			}
1285
		} else {
1286
			if (($number >= 0) && ($number <= pow(2, $maxbits))) {
1287
				return true;
1288
			}
1289
		}
1290
		return false;
1291
	}
1292
}
1293
1294
if (!function_exists('safe_parse_url')) {
1295
	function safe_parse_url($url) {
1296
		ob_start();
1297
		$parts = parse_url($url);
1298
		$errormessage = ob_get_contents();
0 ignored issues
show
Unused Code introduced by
$errormessage is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1299
		ob_end_clean();
1300
		$parts['scheme'] = (isset($parts['scheme']) ? $parts['scheme'] : '');
1301
		$parts['host']   = (isset($parts['host'])   ? $parts['host']   : '');
1302
		$parts['user']   = (isset($parts['user'])   ? $parts['user']   : '');
1303
		$parts['pass']   = (isset($parts['pass'])   ? $parts['pass']   : '');
1304
		$parts['path']   = (isset($parts['path'])   ? $parts['path']   : '');
1305
		$parts['query']  = (isset($parts['query'])  ? $parts['query']  : '');
1306
		return $parts;
1307
	}
1308
}
1309
1310
if (!function_exists('IsValidURL')) {
1311
	function IsValidURL($url, $allowUserPass=false) {
1312
		if ($url == '') {
1313
			return false;
1314
		}
1315
		if ($allowUserPass !== true) {
1316
			if (strstr($url, '@')) {
1317
				// in the format http://user:[email protected]  or http://[email protected]
1318
				// but could easily be somebody incorrectly entering an email address in place of a URL
1319
				return false;
1320
			}
1321
		}
1322
		if ($parts = safe_parse_url($url)) {
1323
			if (($parts['scheme'] != 'http') && ($parts['scheme'] != 'https') && ($parts['scheme'] != 'ftp') && ($parts['scheme'] != 'gopher')) {
1324
				return false;
1325
			} elseif (!preg_match("#^[[:alnum:]]([-.]?[0-9a-z])*\.[a-z]{2,3}#i$", $parts['host'], $regs) && !preg_match('#^[0-9]{1,3}(\.[0-9]{1,3}){3}$#', $parts['host'])) {
1326
				return false;
1327
			} elseif (!preg_match("#^([[:alnum:]-]|[\_])*$#i", $parts['user'], $regs)) {
1328
				return false;
1329
			} elseif (!preg_match("#^([[:alnum:]-]|[\_])*$#i", $parts['pass'], $regs)) {
1330
				return false;
1331
			} elseif (!preg_match("#^[[:alnum:]/_\.@~-]*$#i", $parts['path'], $regs)) {
1332
				return false;
1333
			} elseif (!preg_match("#^[[:alnum:]?&=+:;_()%#/,\.-]*$#i", $parts['query'], $regs)) {
1334
				return false;
1335
			} else {
1336
				return true;
1337
			}
1338
		}
1339
		return false;
1340
	}
1341
}
1342
1343
echo '<form action="'.htmlentities($_SERVER['PHP_SELF'], ENT_QUOTES).'" method="get">';
1344
echo 'Enter 4 hex bytes of MPEG-audio header (ie <I>FF FA 92 44</I>)<BR>';
1345
echo '<input type="text" name="HeaderHexBytes" value="'.htmlentities(isset($_POST['HeaderHexBytes']) ? strtoupper($_POST['HeaderHexBytes']) : '', ENT_QUOTES).'" size="11" maxlength="11">';
1346
echo '<input type="submit" name="Analyze" value="Analyze"></form>';
1347
echo '<hr>';
1348
1349
echo '<form action="'.htmlentities($_SERVER['PHP_SELF'], ENT_QUOTES).'" method="get">';
1350
echo 'Generate a MPEG-audio 4-byte header from these values:<BR>';
1351
echo '<table border="0">';
1352
1353
$MPEGgenerateValues = array(
1354
	'version'       => array('1', '2', '2.5'),
1355
	'layer'         => array('I', 'II', 'III'),
1356
	'protection'    => array('Y', 'N'),
1357
	'bitrate'       => array('free', '8', '16', '24', '32', '40', '48', '56', '64', '80', '96', '112', '128', '144', '160', '176', '192', '224', '256', '288', '320', '352', '384', '416', '448'),
1358
	'frequency'     => array('8000', '11025', '12000', '16000', '22050', '24000', '32000', '44100', '48000'),
1359
	'padding'       => array('Y', 'N'),
1360
	'private'       => array('Y', 'N'),
1361
	'channelmode'   => array('stereo', 'joint stereo', 'dual channel', 'mono'),
1362
	'modeextension' => array('none', 'IS', 'MS', 'IS+MS', '4-31', '8-31', '12-31', '16-31'),
1363
	'copyright'     => array('Y', 'N'),
1364
	'original'      => array('Y', 'N'),
1365
	'emphasis'      => array('none', '50/15ms', 'CCIT J.17'),
1366
);
1367
1368
foreach ($MPEGgenerateValues as $name => $dataarray) {
1369
	echo '<tr><th>'.$name.':</th><td><select name="'.$name.'">';
1370
	foreach ($dataarray as $key => $value) {
1371
		echo '<option'.((isset($_POST["$name"]) && ($_POST["$name"] == $value)) ? ' SELECTED' : '').'>'.$value.'</option>';
1372
	}
1373
	echo '</select></td></tr>';
1374
}
1375
1376
if (isset($_POST['bitrate'])) {
1377
	echo '<tr><th>Frame Length:</th><td>'.(int) MPEGaudioFrameLength($_POST['bitrate'], $_POST['version'], $_POST['layer'], (($_POST['padding'] == 'Y') ? '1' : '0'), $_POST['frequency']).'</td></tr>';
1378
}
1379
echo '</table>';
1380
echo '<input type="submit" name="Generate" value="Generate"></form>';
1381
echo '<hr>';
1382
1383
1384
if (isset($_POST['Analyze']) && $_POST['HeaderHexBytes']) {
1385
1386
	$headerbytearray = explode(' ', $_POST['HeaderHexBytes']);
1387
	if (count($headerbytearray) != 4) {
1388
		die('Invalid byte pattern');
1389
	}
1390
	$headerstring = '';
1391
	foreach ($headerbytearray as $textbyte) {
1392
		$headerstring .= chr(hexdec($textbyte));
1393
	}
1394
1395
	$MP3fileInfo['error'] = '';
1396
1397
	$MPEGheaderRawArray = MPEGaudioHeaderDecode(substr($headerstring, 0, 4));
1398
1399
	if (MPEGaudioHeaderValid($MPEGheaderRawArray, true)) {
1400
1401
		$MP3fileInfo['raw'] = $MPEGheaderRawArray;
1402
1403
		$MP3fileInfo['version']              = MPEGaudioVersionLookup($MP3fileInfo['raw']['version']);
1404
		$MP3fileInfo['layer']                = MPEGaudioLayerLookup($MP3fileInfo['raw']['layer']);
1405
		$MP3fileInfo['protection']           = MPEGaudioCRCLookup($MP3fileInfo['raw']['protection']);
1406
		$MP3fileInfo['bitrate']              = MPEGaudioBitrateLookup($MP3fileInfo['version'], $MP3fileInfo['layer'], $MP3fileInfo['raw']['bitrate']);
1407
		$MP3fileInfo['frequency']            = MPEGaudioFrequencyLookup($MP3fileInfo['version'], $MP3fileInfo['raw']['sample_rate']);
1408
		$MP3fileInfo['padding']              = (bool) $MP3fileInfo['raw']['padding'];
1409
		$MP3fileInfo['private']              = (bool) $MP3fileInfo['raw']['private'];
1410
		$MP3fileInfo['channelmode']          = MPEGaudioChannelModeLookup($MP3fileInfo['raw']['channelmode']);
1411
		$MP3fileInfo['channels']             = (($MP3fileInfo['channelmode'] == 'mono') ? 1 : 2);
1412
		$MP3fileInfo['modeextension']        = MPEGaudioModeExtensionLookup($MP3fileInfo['layer'], $MP3fileInfo['raw']['modeextension']);
1413
		$MP3fileInfo['copyright']            = (bool) $MP3fileInfo['raw']['copyright'];
1414
		$MP3fileInfo['original']             = (bool) $MP3fileInfo['raw']['original'];
1415
		$MP3fileInfo['emphasis']             = MPEGaudioEmphasisLookup($MP3fileInfo['raw']['emphasis']);
1416
1417
		if ($MP3fileInfo['protection']) {
1418
			$MP3fileInfo['crc'] = BigEndian2Int(substr($headerstring, 4, 2));
1419
		}
1420
1421
		if ($MP3fileInfo['frequency'] > 0) {
1422
			$MP3fileInfo['framelength'] = MPEGaudioFrameLength($MP3fileInfo['bitrate'], $MP3fileInfo['version'], $MP3fileInfo['layer'], (int) $MP3fileInfo['padding'], $MP3fileInfo['frequency']);
1423
		}
1424
		if ($MP3fileInfo['bitrate'] != 'free') {
1425
			$MP3fileInfo['bitrate'] *= 1000;
1426
		}
1427
1428
	} else {
1429
1430
		$MP3fileInfo['error'] .= "\n".'Invalid MPEG audio header';
1431
1432
	}
1433
1434
	if (!$MP3fileInfo['error']) {
1435
		unset($MP3fileInfo['error']);
1436
	}
1437
1438
	echo table_var_dump($MP3fileInfo);
1439
1440
} elseif (isset($_POST['Generate'])) {
1441
1442
	// AAAA AAAA  AAAB BCCD  EEEE FFGH  IIJJ KLMM
1443
1444
	$headerbitstream  = '11111111111';                               // A - Frame sync (all bits set)
1445
1446
	$MPEGversionLookup = array('2.5'=>'00', '2'=>'10', '1'=>'11');
1447
	$headerbitstream .= $MPEGversionLookup[$_POST['version']];       // B - MPEG Audio version ID
1448
1449
	$MPEGlayerLookup = array('III'=>'01', 'II'=>'10', 'I'=>'11');
1450
	$headerbitstream .= $MPEGlayerLookup[$_POST['layer']];           // C - Layer description
1451
1452
	$headerbitstream .= (($_POST['protection'] == 'Y') ? '0' : '1'); // D - Protection bit
1453
1454
	$MPEGaudioBitrateLookup['1']['I']     = array('free'=>'0000', '32'=>'0001', '64'=>'0010', '96'=>'0011', '128'=>'0100', '160'=>'0101', '192'=>'0110', '224'=>'0111', '256'=>'1000', '288'=>'1001', '320'=>'1010', '352'=>'1011', '384'=>'1100', '416'=>'1101', '448'=>'1110');
1455
	$MPEGaudioBitrateLookup['1']['II']    = array('free'=>'0000', '32'=>'0001', '48'=>'0010', '56'=>'0011',  '64'=>'0100',  '80'=>'0101',  '96'=>'0110', '112'=>'0111', '128'=>'1000', '160'=>'1001', '192'=>'1010', '224'=>'1011', '256'=>'1100', '320'=>'1101', '384'=>'1110');
1456
	$MPEGaudioBitrateLookup['1']['III']   = array('free'=>'0000', '32'=>'0001', '40'=>'0010', '48'=>'0011',  '56'=>'0100',  '64'=>'0101',  '80'=>'0110',  '96'=>'0111', '112'=>'1000', '128'=>'1001', '160'=>'1010', '192'=>'1011', '224'=>'1100', '256'=>'1101', '320'=>'1110');
1457
	$MPEGaudioBitrateLookup['2']['I']     = array('free'=>'0000', '32'=>'0001', '48'=>'0010', '56'=>'0011',  '64'=>'0100',  '80'=>'0101',  '96'=>'0110', '112'=>'0111', '128'=>'1000', '144'=>'1001', '160'=>'1010', '176'=>'1011', '192'=>'1100', '224'=>'1101', '256'=>'1110');
1458
	$MPEGaudioBitrateLookup['2']['II']    = array('free'=>'0000',  '8'=>'0001', '16'=>'0010', '24'=>'0011',  '32'=>'0100',  '40'=>'0101',  '48'=>'0110',  '56'=>'0111',  '64'=>'1000',  '80'=>'1001',  '96'=>'1010', '112'=>'1011', '128'=>'1100', '144'=>'1101', '160'=>'1110');
1459
	$MPEGaudioBitrateLookup['2']['III']   = $MPEGaudioBitrateLookup['2']['II'];
1460
	$MPEGaudioBitrateLookup['2.5']['I']   = $MPEGaudioBitrateLookup['2']['I'];
1461
	$MPEGaudioBitrateLookup['2.5']['II']  = $MPEGaudioBitrateLookup['2']['II'];
1462
	$MPEGaudioBitrateLookup['2.5']['III'] = $MPEGaudioBitrateLookup['2']['II'];
1463
	if (isset($MPEGaudioBitrateLookup[$_POST['version']][$_POST['layer']][$_POST['bitrate']])) {
1464
		$headerbitstream .= $MPEGaudioBitrateLookup[$_POST['version']][$_POST['layer']][$_POST['bitrate']]; // E - Bitrate index
1465
	} else {
1466
		die('Invalid <B>Bitrate</B>');
1467
	}
1468
1469
	$MPEGaudioFrequencyLookup['1']   = array('44100'=>'00', '48000'=>'01', '32000'=>'10');
1470
	$MPEGaudioFrequencyLookup['2']   = array('22050'=>'00', '24000'=>'01', '16000'=>'10');
1471
	$MPEGaudioFrequencyLookup['2.5'] = array('11025'=>'00', '12000'=>'01', '8000'=>'10');
1472
	if (isset($MPEGaudioFrequencyLookup[$_POST['version']][$_POST['frequency']])) {
1473
		$headerbitstream .= $MPEGaudioFrequencyLookup[$_POST['version']][$_POST['frequency']];  // F - Sampling rate frequency index
1474
	} else {
1475
		die('Invalid <B>Frequency</B>');
1476
	}
1477
1478
	$headerbitstream .= (($_POST['padding'] == 'Y') ? '1' : '0');            // G - Padding bit
1479
1480
	$headerbitstream .= (($_POST['private'] == 'Y') ? '1' : '0');            // H - Private bit
1481
1482
	$MPEGaudioChannelModeLookup = array('stereo'=>'00', 'joint stereo'=>'01', 'dual channel'=>'10', 'mono'=>'11');
1483
	$headerbitstream .= $MPEGaudioChannelModeLookup[$_POST['channelmode']];  // I - Channel Mode
1484
1485
	$MPEGaudioModeExtensionLookup['I']   = array('4-31'=>'00', '8-31'=>'01', '12-31'=>'10', '16-31'=>'11');
1486
	$MPEGaudioModeExtensionLookup['II']  = $MPEGaudioModeExtensionLookup['I'];
1487
	$MPEGaudioModeExtensionLookup['III'] = array('none'=>'00',   'IS'=>'01',    'MS'=>'10', 'IS+MS'=>'11');
1488
	if ($_POST['channelmode'] != 'joint stereo') {
1489
		$headerbitstream .= '00';
1490
	} elseif (isset($MPEGaudioModeExtensionLookup[$_POST['layer']][$_POST['modeextension']])) {
1491
		$headerbitstream .= $MPEGaudioModeExtensionLookup[$_POST['layer']][$_POST['modeextension']];  // J - Mode extension (Only if Joint stereo)
1492
	} else {
1493
		die('Invalid <B>Mode Extension</B>');
1494
	}
1495
1496
	$headerbitstream .= (($_POST['copyright'] == 'Y') ? '1' : '0');          // K - Copyright
1497
1498
	$headerbitstream .= (($_POST['original']  == 'Y') ? '1' : '0');          // L - Original
1499
1500
	$MPEGaudioEmphasisLookup = array('none'=>'00', '50/15ms'=>'01', 'CCIT J.17'=>'11');
1501
	if (isset($MPEGaudioEmphasisLookup[$_POST['emphasis']])) {
1502
		$headerbitstream .= $MPEGaudioEmphasisLookup[$_POST['emphasis']];    // M - Emphasis
1503
	} else {
1504
		die('Invalid <B>Emphasis</B>');
1505
	}
1506
1507
	echo strtoupper(str_pad(dechex(bindec(substr($headerbitstream,  0, 8))), 2, '0', STR_PAD_LEFT)).' ';
1508
	echo strtoupper(str_pad(dechex(bindec(substr($headerbitstream,  8, 8))), 2, '0', STR_PAD_LEFT)).' ';
1509
	echo strtoupper(str_pad(dechex(bindec(substr($headerbitstream, 16, 8))), 2, '0', STR_PAD_LEFT)).' ';
1510
	echo strtoupper(str_pad(dechex(bindec(substr($headerbitstream, 24, 8))), 2, '0', STR_PAD_LEFT)).'<BR>';
1511
1512
}
1513
1514
function MPEGaudioVersionLookup($rawversion) {
1515
	$MPEGaudioVersionLookup = array('2.5', FALSE, '2', '1');
1516
	return (isset($MPEGaudioVersionLookup["$rawversion"]) ? $MPEGaudioVersionLookup["$rawversion"] : FALSE);
1517
}
1518
1519
function MPEGaudioLayerLookup($rawlayer) {
1520
	$MPEGaudioLayerLookup = array(FALSE, 'III', 'II', 'I');
1521
	return (isset($MPEGaudioLayerLookup["$rawlayer"]) ? $MPEGaudioLayerLookup["$rawlayer"] : FALSE);
1522
}
1523
1524
function MPEGaudioBitrateLookup($version, $layer, $rawbitrate) {
1525
	static $MPEGaudioBitrateLookup;
1526
	if (empty($MPEGaudioBitrateLookup)) {
1527
		$MPEGaudioBitrateLookup = MPEGaudioBitrateArray();
1528
	}
1529
	return (isset($MPEGaudioBitrateLookup["$version"]["$layer"]["$rawbitrate"]) ? $MPEGaudioBitrateLookup["$version"]["$layer"]["$rawbitrate"] : FALSE);
1530
}
1531
1532
function MPEGaudioFrequencyLookup($version, $rawfrequency) {
1533
	static $MPEGaudioFrequencyLookup;
1534
	if (empty($MPEGaudioFrequencyLookup)) {
1535
		$MPEGaudioFrequencyLookup = MPEGaudioFrequencyArray();
1536
	}
1537
	return (isset($MPEGaudioFrequencyLookup["$version"]["$rawfrequency"]) ? $MPEGaudioFrequencyLookup["$version"]["$rawfrequency"] : FALSE);
1538
}
1539
1540
function MPEGaudioChannelModeLookup($rawchannelmode) {
1541
	$MPEGaudioChannelModeLookup = array('stereo', 'joint stereo', 'dual channel', 'mono');
1542
	return (isset($MPEGaudioChannelModeLookup["$rawchannelmode"]) ? $MPEGaudioChannelModeLookup["$rawchannelmode"] : FALSE);
1543
}
1544
1545
function MPEGaudioModeExtensionLookup($layer, $rawmodeextension) {
1546
	$MPEGaudioModeExtensionLookup['I']   = array('4-31', '8-31', '12-31', '16-31');
0 ignored issues
show
Coding Style Comprehensibility introduced by
$MPEGaudioModeExtensionLookup was never initialized. Although not strictly required by PHP, it is generally a good practice to add $MPEGaudioModeExtensionLookup = 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...
1547
	$MPEGaudioModeExtensionLookup['II']  = array('4-31', '8-31', '12-31', '16-31');
1548
	$MPEGaudioModeExtensionLookup['III'] = array('', 'IS', 'MS', 'IS+MS');
1549
	return (isset($MPEGaudioModeExtensionLookup["$layer"]["$rawmodeextension"]) ? $MPEGaudioModeExtensionLookup["$layer"]["$rawmodeextension"] : FALSE);
1550
}
1551
1552
function MPEGaudioEmphasisLookup($rawemphasis) {
1553
	$MPEGaudioEmphasisLookup = array('none', '50/15ms', FALSE, 'CCIT J.17');
1554
	return (isset($MPEGaudioEmphasisLookup["$rawemphasis"]) ? $MPEGaudioEmphasisLookup["$rawemphasis"] : FALSE);
1555
}
1556
1557
function MPEGaudioCRCLookup($CRCbit) {
1558
	// inverse boolean cast :)
1559
	if ($CRCbit == '0') {
1560
		return TRUE;
1561
	} else {
1562
		return FALSE;
1563
	}
1564
}
1565
1566
/////////////////////////////////////////////////////////////////
1567
/// getID3() by James Heinrich <[email protected]>               //
1568
//  available at http://getid3.sourceforge.net                ///
1569
//            or https://www.getid3.org                       ///
1570
/////////////////////////////////////////////////////////////////
1571
//                                                             //
1572
// getid3.mp3.php - part of getID3()                           //
1573
// See getid3.readme.txt for more details                      //
1574
//                                                             //
1575
/////////////////////////////////////////////////////////////////
1576
1577
// number of frames to scan to determine if MPEG-audio sequence is valid
1578
// Lower this number to 5-20 for faster scanning
1579
// Increase this number to 50+ for most accurate detection of valid VBR/CBR
1580
// mpeg-audio streams
1581
define('MPEG_VALID_CHECK_FRAMES', 35);
1582
1583
function getMP3headerFilepointer(&$fd, &$ThisFileInfo) {
1584
1585
	getOnlyMPEGaudioInfo($fd, $ThisFileInfo, $ThisFileInfo['avdataoffset']);
1586
1587 View Code Duplication
	if (isset($ThisFileInfo['mpeg']['audio']['bitrate_mode'])) {
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...
1588
		$ThisFileInfo['audio']['bitrate_mode'] = strtolower($ThisFileInfo['mpeg']['audio']['bitrate_mode']);
1589
	}
1590
1591
	if (((isset($ThisFileInfo['id3v2']) && ($ThisFileInfo['avdataoffset'] > $ThisFileInfo['id3v2']['headerlength'])) || (!isset($ThisFileInfo['id3v2']) && ($ThisFileInfo['avdataoffset'] > 0)))) {
1592
1593
		$ThisFileInfo['warning'] .= "\n".'Unknown data before synch ';
1594
		if (isset($ThisFileInfo['id3v2']['headerlength'])) {
1595
			$ThisFileInfo['warning'] .= '(ID3v2 header ends at '.$ThisFileInfo['id3v2']['headerlength'].', then '.($ThisFileInfo['avdataoffset'] - $ThisFileInfo['id3v2']['headerlength']).' bytes garbage, ';
1596
		} else {
1597
			$ThisFileInfo['warning'] .= '(should be at beginning of file, ';
1598
		}
1599
		$ThisFileInfo['warning'] .= 'synch detected at '.$ThisFileInfo['avdataoffset'].')';
1600
		if ($ThisFileInfo['audio']['bitrate_mode'] == 'cbr') {
1601
			if (!empty($ThisFileInfo['id3v2']['headerlength']) && (($ThisFileInfo['avdataoffset'] - $ThisFileInfo['id3v2']['headerlength']) == $ThisFileInfo['mpeg']['audio']['framelength'])) {
1602
				$ThisFileInfo['warning'] .= '. This is a known problem with some versions of LAME (3.91, 3.92) DLL in CBR mode.';
1603
				$ThisFileInfo['audio']['codec'] = 'LAME';
1604 View Code Duplication
			} elseif (empty($ThisFileInfo['id3v2']['headerlength']) && ($ThisFileInfo['avdataoffset'] == $ThisFileInfo['mpeg']['audio']['framelength'])) {
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...
1605
				$ThisFileInfo['warning'] .= '. This is a known problem with some versions of LAME (3.91, 3.92) DLL in CBR mode.';
1606
				$ThisFileInfo['audio']['codec'] = 'LAME';
1607
			}
1608
		}
1609
1610
	}
1611
1612
	if (isset($ThisFileInfo['mpeg']['audio']['layer']) && ($ThisFileInfo['mpeg']['audio']['layer'] == 'II')) {
1613
		$ThisFileInfo['audio']['dataformat'] = 'mp2';
1614
	} elseif (isset($ThisFileInfo['mpeg']['audio']['layer']) && ($ThisFileInfo['mpeg']['audio']['layer'] == 'I')) {
1615
		$ThisFileInfo['audio']['dataformat'] = 'mp1';
1616
	}
1617 View Code Duplication
	if ($ThisFileInfo['fileformat'] == 'mp3') {
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...
1618
		switch ($ThisFileInfo['audio']['dataformat']) {
1619
			case 'mp1':
1620
			case 'mp2':
1621
			case 'mp3':
1622
				$ThisFileInfo['fileformat'] = $ThisFileInfo['audio']['dataformat'];
1623
				break;
1624
1625
			default:
1626
				$ThisFileInfo['warning'] .= "\n".'Expecting [audio][dataformat] to be mp1/mp2/mp3 when fileformat == mp3, [audio][dataformat] actually "'.$ThisFileInfo['audio']['dataformat'].'"';
1627
				break;
1628
		}
1629
	}
1630
1631
	if (empty($ThisFileInfo['fileformat'])) {
1632
		$ThisFileInfo['error'] .= "\n".'Synch not found';
1633
		unset($ThisFileInfo['fileformat']);
1634
		unset($ThisFileInfo['audio']['bitrate_mode']);
1635
		unset($ThisFileInfo['avdataoffset']);
1636
		unset($ThisFileInfo['avdataend']);
1637
		return false;
1638
	}
1639
1640
	$ThisFileInfo['mime_type']         = 'audio/mpeg';
1641
	$ThisFileInfo['audio']['lossless'] = false;
1642
1643
	// Calculate playtime
1644
	if (!isset($ThisFileInfo['playtime_seconds']) && isset($ThisFileInfo['audio']['bitrate']) && ($ThisFileInfo['audio']['bitrate'] > 0)) {
1645
		$ThisFileInfo['playtime_seconds'] = ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) * 8 / $ThisFileInfo['audio']['bitrate'];
1646
	}
1647
1648
	if (isset($ThisFileInfo['mpeg']['audio']['LAME'])) {
1649
		$ThisFileInfo['audio']['codec'] = 'LAME';
1650 View Code Duplication
		if (!empty($ThisFileInfo['mpeg']['audio']['LAME']['long_version'])) {
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...
1651
			$ThisFileInfo['audio']['encoder'] = trim($ThisFileInfo['mpeg']['audio']['LAME']['long_version']);
1652
		}
1653
	}
1654
1655
	return true;
1656
}
1657
1658
1659
function decodeMPEGaudioHeader($fd, $offset, &$ThisFileInfo, $recursivesearch=true, $ScanAsCBR=false, $FastMPEGheaderScan=false) {
1660
1661
	static $MPEGaudioVersionLookup;
1662
	static $MPEGaudioLayerLookup;
1663
	static $MPEGaudioBitrateLookup;
1664
	static $MPEGaudioFrequencyLookup;
1665
	static $MPEGaudioChannelModeLookup;
1666
	static $MPEGaudioModeExtensionLookup;
1667
	static $MPEGaudioEmphasisLookup;
1668 View Code Duplication
	if (empty($MPEGaudioVersionLookup)) {
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...
1669
		$MPEGaudioVersionLookup       = MPEGaudioVersionArray();
1670
		$MPEGaudioLayerLookup         = MPEGaudioLayerArray();
1671
		$MPEGaudioBitrateLookup       = MPEGaudioBitrateArray();
1672
		$MPEGaudioFrequencyLookup     = MPEGaudioFrequencyArray();
1673
		$MPEGaudioChannelModeLookup   = MPEGaudioChannelModeArray();
1674
		$MPEGaudioModeExtensionLookup = MPEGaudioModeExtensionArray();
1675
		$MPEGaudioEmphasisLookup      = MPEGaudioEmphasisArray();
1676
	}
1677
1678
	if ($offset >= $ThisFileInfo['avdataend']) {
1679
		$ThisFileInfo['error'] .= "\n".'end of file encounter looking for MPEG synch';
1680
		return false;
1681
	}
1682
	fseek($fd, $offset, SEEK_SET);
1683
	$headerstring = fread($fd, 1441); // worse-case max length = 32kHz @ 320kbps layer 3 = 1441 bytes/frame
1684
1685
	// MP3 audio frame structure:
1686
	// $aa $aa $aa $aa [$bb $bb] $cc...
1687
	// where $aa..$aa is the four-byte mpeg-audio header (below)
1688
	// $bb $bb is the optional 2-byte CRC
1689
	// and $cc... is the audio data
1690
1691
	$head4 = substr($headerstring, 0, 4);
1692
1693
	static $MPEGaudioHeaderDecodeCache = array();
1694 View Code Duplication
	if (isset($MPEGaudioHeaderDecodeCache[$head4])) {
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...
1695
		$MPEGheaderRawArray = $MPEGaudioHeaderDecodeCache[$head4];
1696
	} else {
1697
		$MPEGheaderRawArray = MPEGaudioHeaderDecode($head4);
1698
		$MPEGaudioHeaderDecodeCache[$head4] = $MPEGheaderRawArray;
1699
	}
1700
1701
	static $MPEGaudioHeaderValidCache = array();
1702
1703
	// Not in cache
1704
	if (!isset($MPEGaudioHeaderValidCache[$head4])) {
1705
		$MPEGaudioHeaderValidCache[$head4] = MPEGaudioHeaderValid($MPEGheaderRawArray);
1706
	}
1707
1708
	if ($MPEGaudioHeaderValidCache[$head4]) {
1709
		$ThisFileInfo['mpeg']['audio']['raw'] = $MPEGheaderRawArray;
1710
	} else {
1711
		$ThisFileInfo['error'] .= "\n".'Invalid MPEG audio header at offset '.$offset;
1712
		return false;
1713
	}
1714
1715
	if (!$FastMPEGheaderScan) {
1716
1717
		$ThisFileInfo['mpeg']['audio']['version']       = $MPEGaudioVersionLookup[$ThisFileInfo['mpeg']['audio']['raw']['version']];
1718
		$ThisFileInfo['mpeg']['audio']['layer']         = $MPEGaudioLayerLookup[$ThisFileInfo['mpeg']['audio']['raw']['layer']];
1719
1720
		$ThisFileInfo['mpeg']['audio']['channelmode']   = $MPEGaudioChannelModeLookup[$ThisFileInfo['mpeg']['audio']['raw']['channelmode']];
1721
		$ThisFileInfo['mpeg']['audio']['channels']      = (($ThisFileInfo['mpeg']['audio']['channelmode'] == 'mono') ? 1 : 2);
1722
		$ThisFileInfo['mpeg']['audio']['sample_rate']   = $MPEGaudioFrequencyLookup[$ThisFileInfo['mpeg']['audio']['version']][$ThisFileInfo['mpeg']['audio']['raw']['sample_rate']];
1723
		$ThisFileInfo['mpeg']['audio']['protection']    = !$ThisFileInfo['mpeg']['audio']['raw']['protection'];
1724
		$ThisFileInfo['mpeg']['audio']['private']       = (bool) $ThisFileInfo['mpeg']['audio']['raw']['private'];
1725
		$ThisFileInfo['mpeg']['audio']['modeextension'] = $MPEGaudioModeExtensionLookup[$ThisFileInfo['mpeg']['audio']['layer']][$ThisFileInfo['mpeg']['audio']['raw']['modeextension']];
1726
		$ThisFileInfo['mpeg']['audio']['copyright']     = (bool) $ThisFileInfo['mpeg']['audio']['raw']['copyright'];
1727
		$ThisFileInfo['mpeg']['audio']['original']      = (bool) $ThisFileInfo['mpeg']['audio']['raw']['original'];
1728
		$ThisFileInfo['mpeg']['audio']['emphasis']      = $MPEGaudioEmphasisLookup[$ThisFileInfo['mpeg']['audio']['raw']['emphasis']];
1729
1730
		$ThisFileInfo['audio']['channels']    = $ThisFileInfo['mpeg']['audio']['channels'];
1731
		$ThisFileInfo['audio']['sample_rate'] = $ThisFileInfo['mpeg']['audio']['sample_rate'];
1732
1733
		if ($ThisFileInfo['mpeg']['audio']['protection']) {
1734
			$ThisFileInfo['mpeg']['audio']['crc'] = BigEndian2Int(substr($headerstring, 4, 2));
1735
		}
1736
1737
	}
1738
1739
	if ($ThisFileInfo['mpeg']['audio']['raw']['bitrate'] == 15) {
1740
		// http://www.hydrogenaudio.org/?act=ST&f=16&t=9682&st=0
1741
		$ThisFileInfo['warning'] .= "\n".'Invalid bitrate index (15), this is a known bug in free-format MP3s encoded by LAME v3.90 - 3.93.1';
1742
		$ThisFileInfo['mpeg']['audio']['raw']['bitrate'] = 0;
1743
	}
1744
	$ThisFileInfo['mpeg']['audio']['padding'] = (bool) $ThisFileInfo['mpeg']['audio']['raw']['padding'];
1745
	$ThisFileInfo['mpeg']['audio']['bitrate'] = $MPEGaudioBitrateLookup[$ThisFileInfo['mpeg']['audio']['version']][$ThisFileInfo['mpeg']['audio']['layer']][$ThisFileInfo['mpeg']['audio']['raw']['bitrate']];
1746
1747
	if (($ThisFileInfo['mpeg']['audio']['bitrate'] == 'free') && ($offset == $ThisFileInfo['avdataoffset'])) {
1748
		// only skip multiple frame check if free-format bitstream found at beginning of file
1749
		// otherwise is quite possibly simply corrupted data
1750
		$recursivesearch = false;
1751
	}
1752
1753
	// For Layer II there are some combinations of bitrate and mode which are not allowed.
1754
	if (!$FastMPEGheaderScan && ($ThisFileInfo['mpeg']['audio']['layer'] == 'II')) {
1755
1756
		$ThisFileInfo['audio']['dataformat'] = 'mp2';
1757
		switch ($ThisFileInfo['mpeg']['audio']['channelmode']) {
1758
1759
			case 'mono':
1760
				if (($ThisFileInfo['mpeg']['audio']['bitrate'] == 'free') || ($ThisFileInfo['mpeg']['audio']['bitrate'] <= 192)) {
1761
					// these are ok
1762 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...
1763
					$ThisFileInfo['error'] .= "\n".$ThisFileInfo['mpeg']['audio']['bitrate'].'kbps not allowed in Layer II, '.$ThisFileInfo['mpeg']['audio']['channelmode'].'.';
1764
					return false;
1765
				}
1766
				break;
1767
1768
			case 'stereo':
1769
			case 'joint stereo':
1770
			case 'dual channel':
1771
				if (($ThisFileInfo['mpeg']['audio']['bitrate'] == 'free') || ($ThisFileInfo['mpeg']['audio']['bitrate'] == 64) || ($ThisFileInfo['mpeg']['audio']['bitrate'] >= 96)) {
1772
					// these are ok
1773 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...
1774
					$ThisFileInfo['error'] .= "\n".$ThisFileInfo['mpeg']['audio']['bitrate'].'kbps not allowed in Layer II, '.$ThisFileInfo['mpeg']['audio']['channelmode'].'.';
1775
					return false;
1776
				}
1777
				break;
1778
1779
		}
1780
1781
	}
1782
1783
1784
	if ($ThisFileInfo['audio']['sample_rate'] > 0) {
1785
		$ThisFileInfo['mpeg']['audio']['framelength'] = MPEGaudioFrameLength($ThisFileInfo['mpeg']['audio']['bitrate'], $ThisFileInfo['mpeg']['audio']['version'], $ThisFileInfo['mpeg']['audio']['layer'], (int) $ThisFileInfo['mpeg']['audio']['padding'], $ThisFileInfo['audio']['sample_rate']);
1786
	}
1787
1788
	if ($ThisFileInfo['mpeg']['audio']['bitrate'] != 'free') {
1789
1790
		$ThisFileInfo['audio']['bitrate'] = 1000 * $ThisFileInfo['mpeg']['audio']['bitrate'];
1791
1792
		if (isset($ThisFileInfo['mpeg']['audio']['framelength'])) {
1793
			$nextframetestoffset = $offset + $ThisFileInfo['mpeg']['audio']['framelength'];
1794
		} else {
1795
			$ThisFileInfo['error'] .= "\n".'Frame at offset('.$offset.') is has an invalid frame length.';
1796
			return false;
1797
		}
1798
1799
	}
1800
1801
	$ExpectedNumberOfAudioBytes = 0;
1802
1803
	////////////////////////////////////////////////////////////////////////////////////
1804
	// Variable-bitrate headers
1805
1806
	if (substr($headerstring, 4 + 32, 4) == 'VBRI') {
1807
		// Fraunhofer VBR header is hardcoded 'VBRI' at offset 0x24 (36)
1808
		// specs taken from http://minnie.tuhs.org/pipermail/mp3encoder/2001-January/001800.html
1809
1810
		$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = 'vbr';
1811
		$ThisFileInfo['mpeg']['audio']['VBR_method']   = 'Fraunhofer';
1812
		$ThisFileInfo['audio']['codec']                = 'Fraunhofer';
1813
1814
		$SideInfoData = substr($headerstring, 4 + 2, 32);
0 ignored issues
show
Unused Code introduced by
$SideInfoData is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1815
1816
		$FraunhoferVBROffset = 36;
1817
1818
		$ThisFileInfo['mpeg']['audio']['VBR_encoder_version']     = BigEndian2Int(substr($headerstring, $FraunhoferVBROffset +  4, 2));
1819
		$ThisFileInfo['mpeg']['audio']['VBR_encoder_delay']       = BigEndian2Int(substr($headerstring, $FraunhoferVBROffset +  6, 2));
1820
		$ThisFileInfo['mpeg']['audio']['VBR_quality']             = BigEndian2Int(substr($headerstring, $FraunhoferVBROffset +  8, 2));
1821
		$ThisFileInfo['mpeg']['audio']['VBR_bytes']               = BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 10, 4));
1822
		$ThisFileInfo['mpeg']['audio']['VBR_frames']              = BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 14, 4));
1823
		$ThisFileInfo['mpeg']['audio']['VBR_seek_offsets']        = BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 18, 2));
1824
		//$ThisFileInfo['mpeg']['audio']['reserved']              = BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 20, 4)); // hardcoded $00 $01 $00 $02  - purpose unknown
1825
		$ThisFileInfo['mpeg']['audio']['VBR_seek_offsets_stride'] = BigEndian2Int(substr($headerstring, $FraunhoferVBROffset + 24, 2));
1826
1827
		$ExpectedNumberOfAudioBytes = $ThisFileInfo['mpeg']['audio']['VBR_bytes'];
1828
1829
		$previousbyteoffset = $offset;
1830
		for ($i = 0; $i < $ThisFileInfo['mpeg']['audio']['VBR_seek_offsets']; $i++) {
1831
			$Fraunhofer_OffsetN = BigEndian2Int(substr($headerstring, $FraunhoferVBROffset, 2));
1832
			$FraunhoferVBROffset += 2;
1833
			$ThisFileInfo['mpeg']['audio']['VBR_offsets_relative'][$i] = $Fraunhofer_OffsetN;
1834
			$ThisFileInfo['mpeg']['audio']['VBR_offsets_absolute'][$i] = $Fraunhofer_OffsetN + $previousbyteoffset;
1835
			$previousbyteoffset += $Fraunhofer_OffsetN;
1836
		}
1837
1838
1839
	} else {
1840
1841
		// Xing VBR header is hardcoded 'Xing' at a offset 0x0D (13), 0x15 (21) or 0x24 (36)
1842
		// depending on MPEG layer and number of channels
1843
1844
		if ($ThisFileInfo['mpeg']['audio']['version'] == '1') {
1845 View Code Duplication
			if ($ThisFileInfo['mpeg']['audio']['channelmode'] == 'mono') {
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...
1846
				// MPEG-1 (mono)
1847
				$VBRidOffset  = 4 + 17; // 0x15
1848
				$SideInfoData = substr($headerstring, 4 + 2, 17);
0 ignored issues
show
Unused Code introduced by
$SideInfoData is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1849
			} else {
1850
				// MPEG-1 (stereo, joint-stereo, dual-channel)
1851
				$VBRidOffset = 4 + 32; // 0x24
1852
				$SideInfoData = substr($headerstring, 4 + 2, 32);
0 ignored issues
show
Unused Code introduced by
$SideInfoData is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1853
			}
1854 View Code Duplication
		} else { // 2 or 2.5
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...
1855
			if ($ThisFileInfo['mpeg']['audio']['channelmode'] == 'mono') {
1856
				// MPEG-2, MPEG-2.5 (mono)
1857
				$VBRidOffset = 4 + 9;  // 0x0D
1858
				$SideInfoData = substr($headerstring, 4 + 2, 9);
0 ignored issues
show
Unused Code introduced by
$SideInfoData is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1859
			} else {
1860
				// MPEG-2, MPEG-2.5 (stereo, joint-stereo, dual-channel)
1861
				$VBRidOffset = 4 + 17; // 0x15
1862
				$SideInfoData = substr($headerstring, 4 + 2, 17);
0 ignored issues
show
Unused Code introduced by
$SideInfoData is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1863
			}
1864
		}
1865
1866
		if ((substr($headerstring, $VBRidOffset, strlen('Xing')) == 'Xing') || (substr($headerstring, $VBRidOffset, strlen('Info')) == 'Info')) {
1867
			// 'Xing' is traditional Xing VBR frame
1868
			// 'Info' is LAME-encoded CBR (This was done to avoid CBR files to be recognized as traditional Xing VBR files by some decoders.)
1869
1870
			$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = 'vbr';
1871
			$ThisFileInfo['mpeg']['audio']['VBR_method']   = 'Xing';
1872
1873
			$ThisFileInfo['mpeg']['audio']['xing_flags_raw'] = BigEndian2Int(substr($headerstring, $VBRidOffset + 4, 4));
1874
1875
			$ThisFileInfo['mpeg']['audio']['xing_flags']['frames']    = (bool) ($ThisFileInfo['mpeg']['audio']['xing_flags_raw'] & 0x00000001);
1876
			$ThisFileInfo['mpeg']['audio']['xing_flags']['bytes']     = (bool) ($ThisFileInfo['mpeg']['audio']['xing_flags_raw'] & 0x00000002);
1877
			$ThisFileInfo['mpeg']['audio']['xing_flags']['toc']       = (bool) ($ThisFileInfo['mpeg']['audio']['xing_flags_raw'] & 0x00000004);
1878
			$ThisFileInfo['mpeg']['audio']['xing_flags']['vbr_scale'] = (bool) ($ThisFileInfo['mpeg']['audio']['xing_flags_raw'] & 0x00000008);
1879
1880 View Code Duplication
			if ($ThisFileInfo['mpeg']['audio']['xing_flags']['frames']) {
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...
1881
				$ThisFileInfo['mpeg']['audio']['VBR_frames'] = BigEndian2Int(substr($headerstring, $VBRidOffset +  8, 4));
1882
			}
1883 View Code Duplication
			if ($ThisFileInfo['mpeg']['audio']['xing_flags']['bytes']) {
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...
1884
				$ThisFileInfo['mpeg']['audio']['VBR_bytes']  = BigEndian2Int(substr($headerstring, $VBRidOffset + 12, 4));
1885
			}
1886
1887
			if (($ThisFileInfo['mpeg']['audio']['bitrate'] == 'free') && !empty($ThisFileInfo['mpeg']['audio']['VBR_frames']) && !empty($ThisFileInfo['mpeg']['audio']['VBR_bytes'])) {
1888
				$framelengthfloat = $ThisFileInfo['mpeg']['audio']['VBR_bytes'] / $ThisFileInfo['mpeg']['audio']['VBR_frames'];
1889 View Code Duplication
				if ($ThisFileInfo['mpeg']['audio']['layer'] == 'I') {
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...
1890
					// BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
1891
					$ThisFileInfo['audio']['bitrate'] = ((($framelengthfloat / 4) - intval($ThisFileInfo['mpeg']['audio']['padding'])) * $ThisFileInfo['mpeg']['audio']['sample_rate']) / 12;
1892
				} else {
1893
					// Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144
1894
					$ThisFileInfo['audio']['bitrate'] = (($framelengthfloat - intval($ThisFileInfo['mpeg']['audio']['padding'])) * $ThisFileInfo['mpeg']['audio']['sample_rate']) / 144;
1895
				}
1896
				$ThisFileInfo['mpeg']['audio']['framelength'] = floor($framelengthfloat);
1897
			}
1898
1899
			if ($ThisFileInfo['mpeg']['audio']['xing_flags']['toc']) {
1900
				$LAMEtocData = substr($headerstring, $VBRidOffset + 16, 100);
1901
				for ($i = 0; $i < 100; $i++) {
1902
					$ThisFileInfo['mpeg']['audio']['toc'][$i] = ord($LAMEtocData[$i]);
1903
				}
1904
			}
1905 View Code Duplication
			if ($ThisFileInfo['mpeg']['audio']['xing_flags']['vbr_scale']) {
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...
1906
				$ThisFileInfo['mpeg']['audio']['VBR_scale'] = BigEndian2Int(substr($headerstring, $VBRidOffset + 116, 4));
1907
			}
1908
1909
			// http://gabriel.mp3-tech.org/mp3infotag.html
1910
			if (substr($headerstring, $VBRidOffset + 120, 4) == 'LAME') {
1911
				$ThisFileInfo['mpeg']['audio']['LAME']['long_version']  = substr($headerstring, $VBRidOffset + 120, 20);
1912
				$ThisFileInfo['mpeg']['audio']['LAME']['short_version'] = substr($ThisFileInfo['mpeg']['audio']['LAME']['long_version'], 0, 9);
1913
				$ThisFileInfo['mpeg']['audio']['LAME']['long_version']  = rtrim($ThisFileInfo['mpeg']['audio']['LAME']['long_version'], "\x55\xAA");
1914
1915
				if ($ThisFileInfo['mpeg']['audio']['LAME']['short_version'] >= 'LAME3.90.') {
1916
1917
					// It the LAME tag was only introduced in LAME v3.90
1918
					// http://www.hydrogenaudio.org/?act=ST&f=15&t=9933
1919
1920
					// Offsets of various bytes in http://gabriel.mp3-tech.org/mp3infotag.html
1921
					// are assuming a 'Xing' identifier offset of 0x24, which is the case for
1922
					// MPEG-1 non-mono, but not for other combinations
1923
					$LAMEtagOffsetContant = $VBRidOffset - 0x24;
1924
1925
					// byte $9B  VBR Quality
1926
					// This field is there to indicate a quality level, although the scale was not precised in the original Xing specifications.
1927
					// Actually overwrites original Xing bytes
1928
					unset($ThisFileInfo['mpeg']['audio']['VBR_scale']);
1929
					$ThisFileInfo['mpeg']['audio']['LAME']['vbr_quality'] = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0x9B, 1));
1930
1931
					// bytes $9C-$A4  Encoder short VersionString
1932
					$ThisFileInfo['mpeg']['audio']['LAME']['short_version'] = substr($headerstring, $LAMEtagOffsetContant + 0x9C, 9);
1933
					$ThisFileInfo['mpeg']['audio']['LAME']['long_version']  = $ThisFileInfo['mpeg']['audio']['LAME']['short_version'];
1934
1935
					// byte $A5  Info Tag revision + VBR method
1936
					$LAMEtagRevisionVBRmethod = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA5, 1));
1937
1938
					$ThisFileInfo['mpeg']['audio']['LAME']['tag_revision']      = ($LAMEtagRevisionVBRmethod & 0xF0) >> 4;
1939
					$ThisFileInfo['mpeg']['audio']['LAME']['raw']['vbr_method'] =  $LAMEtagRevisionVBRmethod & 0x0F;
1940
					$ThisFileInfo['mpeg']['audio']['LAME']['vbr_method']        = LAMEvbrMethodLookup($ThisFileInfo['mpeg']['audio']['LAME']['raw']['vbr_method']);
1941
1942
					// byte $A6  Lowpass filter value
1943
					$ThisFileInfo['mpeg']['audio']['LAME']['lowpass_frequency'] = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xA6, 1)) * 100;
1944
1945
					// bytes $A7-$AE  Replay Gain
1946
					// http://privatewww.essex.ac.uk/~djmrob/replaygain/rg_data_format.html
1947
					// bytes $A7-$AA : 32 bit floating point "Peak signal amplitude"
1948
					$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['peak_amplitude'] = BigEndian2Float(substr($headerstring, $LAMEtagOffsetContant + 0xA7, 4));
1949
					$ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_radio']      =   BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAB, 2));
1950
					$ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_audiophile'] =   BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAD, 2));
1951
1952
					if ($ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['peak_amplitude'] == 0) {
1953
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['peak_amplitude'] = false;
1954
					}
1955
1956 View Code Duplication
					if ($ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_radio'] != 0) {
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...
1957
						require_once(GETID3_INCLUDEPATH.'getid3.rgad.php');
1958
1959
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['raw']['name']        = ($ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_radio'] & 0xE000) >> 13;
1960
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['raw']['originator']  = ($ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_radio'] & 0x1C00) >> 10;
1961
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['raw']['sign_bit']    = ($ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_radio'] & 0x0200) >> 9;
1962
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['raw']['gain_adjust'] =  $ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_radio'] & 0x01FF;
1963
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['name']       = RGADnameLookup($ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['raw']['name']);
1964
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['originator'] = RGADoriginatorLookup($ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['raw']['originator']);
1965
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['gain_db']    = RGADadjustmentLookup($ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['raw']['gain_adjust'], $ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['raw']['sign_bit']);
1966
1967
						if ($ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['peak_amplitude'] !== false) {
1968
							$ThisFileInfo['replay_gain']['radio']['peak']   = $ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['peak_amplitude'];
1969
						}
1970
						$ThisFileInfo['replay_gain']['radio']['originator'] = $ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['originator'];
1971
						$ThisFileInfo['replay_gain']['radio']['adjustment'] = $ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['radio']['gain_db'];
1972
					}
1973 View Code Duplication
					if ($ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_audiophile'] != 0) {
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...
1974
						require_once(GETID3_INCLUDEPATH.'getid3.rgad.php');
1975
1976
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['raw']['name']        = ($ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_audiophile'] & 0xE000) >> 13;
1977
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['raw']['originator']  = ($ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_audiophile'] & 0x1C00) >> 10;
1978
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['raw']['sign_bit']    = ($ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_audiophile'] & 0x0200) >> 9;
1979
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['raw']['gain_adjust'] = $ThisFileInfo['mpeg']['audio']['LAME']['raw']['RGAD_audiophile'] & 0x01FF;
1980
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['name']       = RGADnameLookup($ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['raw']['name']);
1981
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['originator'] = RGADoriginatorLookup($ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['raw']['originator']);
1982
						$ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['gain_db']    = RGADadjustmentLookup($ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['raw']['gain_adjust'], $ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['raw']['sign_bit']);
1983
1984
						if ($ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['peak_amplitude'] !== false) {
1985
							$ThisFileInfo['replay_gain']['audiophile']['peak']   = $ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['peak_amplitude'];
1986
						}
1987
						$ThisFileInfo['replay_gain']['audiophile']['originator'] = $ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['originator'];
1988
						$ThisFileInfo['replay_gain']['audiophile']['adjustment'] = $ThisFileInfo['mpeg']['audio']['LAME']['RGAD']['audiophile']['gain_db'];
1989
					}
1990
1991
1992
					// byte $AF  Encoding flags + ATH Type
1993
					$EncodingFlagsATHtype = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xAF, 1));
1994
					$ThisFileInfo['mpeg']['audio']['LAME']['encoding_flags']['nspsytune']   = (bool) ($EncodingFlagsATHtype & 0x10);
1995
					$ThisFileInfo['mpeg']['audio']['LAME']['encoding_flags']['nssafejoint'] = (bool) ($EncodingFlagsATHtype & 0x20);
1996
					$ThisFileInfo['mpeg']['audio']['LAME']['encoding_flags']['nogap_next']  = (bool) ($EncodingFlagsATHtype & 0x40);
1997
					$ThisFileInfo['mpeg']['audio']['LAME']['encoding_flags']['nogap_prev']  = (bool) ($EncodingFlagsATHtype & 0x80);
1998
					$ThisFileInfo['mpeg']['audio']['LAME']['ath_type']                      =         $EncodingFlagsATHtype & 0x0F;
1999
2000
					// byte $B0  if ABR {specified bitrate} else {minimal bitrate}
2001
					$ABRbitrateMinBitrate = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB0, 1));
2002
					if ($ThisFileInfo['mpeg']['audio']['LAME']['raw']['vbr_method'] == 2) { // Average BitRate (ABR)
2003
						$ThisFileInfo['mpeg']['audio']['LAME']['bitrate_abr'] = $ABRbitrateMinBitrate;
2004
					} elseif ($ABRbitrateMinBitrate > 0) { // Variable BitRate (VBR) - minimum bitrate
2005
						$ThisFileInfo['mpeg']['audio']['LAME']['bitrate_min'] = $ABRbitrateMinBitrate;
2006
					}
2007
2008
					// bytes $B1-$B3  Encoder delays
2009
					$EncoderDelays = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB1, 3));
2010
					$ThisFileInfo['mpeg']['audio']['LAME']['encoder_delay'] = ($EncoderDelays & 0xFFF000) >> 12;
2011
					$ThisFileInfo['mpeg']['audio']['LAME']['end_padding']   =  $EncoderDelays & 0x000FFF;
2012
2013
					// byte $B4  Misc
2014
					$MiscByte = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB4, 1));
2015
					$ThisFileInfo['mpeg']['audio']['LAME']['raw']['noise_shaping']       = ($MiscByte & 0x03);
2016
					$ThisFileInfo['mpeg']['audio']['LAME']['raw']['stereo_mode']         = ($MiscByte & 0x1C) >> 2;
2017
					$ThisFileInfo['mpeg']['audio']['LAME']['raw']['not_optimal_quality'] = ($MiscByte & 0x20) >> 5;
2018
					$ThisFileInfo['mpeg']['audio']['LAME']['raw']['source_sample_freq']  = ($MiscByte & 0xC0) >> 6;
2019
					$ThisFileInfo['mpeg']['audio']['LAME']['noise_shaping']       = $ThisFileInfo['mpeg']['audio']['LAME']['raw']['noise_shaping'];
2020
					$ThisFileInfo['mpeg']['audio']['LAME']['stereo_mode']         = LAMEmiscStereoModeLookup($ThisFileInfo['mpeg']['audio']['LAME']['raw']['stereo_mode']);
2021
					$ThisFileInfo['mpeg']['audio']['LAME']['not_optimal_quality'] = (bool) $ThisFileInfo['mpeg']['audio']['LAME']['raw']['not_optimal_quality'];
2022
					$ThisFileInfo['mpeg']['audio']['LAME']['source_sample_freq']  = LAMEmiscSourceSampleFrequencyLookup($ThisFileInfo['mpeg']['audio']['LAME']['raw']['source_sample_freq']);
2023
2024
					// byte $B5  MP3 Gain
2025
					$ThisFileInfo['mpeg']['audio']['LAME']['raw']['mp3_gain'] = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB5, 1), false, true);
2026
					$ThisFileInfo['mpeg']['audio']['LAME']['mp3_gain_db']     = 1.5 * $ThisFileInfo['mpeg']['audio']['LAME']['raw']['mp3_gain'];
2027
					$ThisFileInfo['mpeg']['audio']['LAME']['mp3_gain_factor'] = pow(2, ($ThisFileInfo['mpeg']['audio']['LAME']['mp3_gain_db'] / 6));
2028
2029
					// bytes $B6-$B7  Preset and surround info
2030
					$PresetSurroundBytes = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB6, 2));
2031
					// Reserved                                                    = ($PresetSurroundBytes & 0xC000);
2032
					$ThisFileInfo['mpeg']['audio']['LAME']['raw']['surround_info'] = ($PresetSurroundBytes & 0x3800);
2033
					$ThisFileInfo['mpeg']['audio']['LAME']['surround_info']        = LAMEsurroundInfoLookup($ThisFileInfo['mpeg']['audio']['LAME']['raw']['surround_info']);
2034
					$ThisFileInfo['mpeg']['audio']['LAME']['preset_used_id']       = ($PresetSurroundBytes & 0x07FF);
2035
2036
					// bytes $B8-$BB  MusicLength
2037
					$ThisFileInfo['mpeg']['audio']['LAME']['audio_bytes'] = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xB8, 4));
2038
					$ExpectedNumberOfAudioBytes = (($ThisFileInfo['mpeg']['audio']['LAME']['audio_bytes'] > 0) ? $ThisFileInfo['mpeg']['audio']['LAME']['audio_bytes'] : $ThisFileInfo['mpeg']['audio']['VBR_bytes']);
2039
2040
					// bytes $BC-$BD  MusicCRC
2041
					$ThisFileInfo['mpeg']['audio']['LAME']['music_crc']    = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBC, 2));
2042
2043
					// bytes $BE-$BF  CRC-16 of Info Tag
2044
					$ThisFileInfo['mpeg']['audio']['LAME']['lame_tag_crc'] = BigEndian2Int(substr($headerstring, $LAMEtagOffsetContant + 0xBE, 2));
2045
2046
2047
					// LAME CBR
2048
					if ($ThisFileInfo['mpeg']['audio']['LAME']['raw']['vbr_method'] == 1) {
2049
2050
						$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = 'cbr';
2051 View Code Duplication
						if (empty($ThisFileInfo['mpeg']['audio']['bitrate']) || ($ThisFileInfo['mpeg']['audio']['LAME']['bitrate_min'] != 255)) {
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...
2052
							$ThisFileInfo['mpeg']['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['LAME']['bitrate_min'];
2053
						}
2054
2055
					}
2056
2057
				}
2058
			}
2059
2060
		} else {
2061
2062
			// not Fraunhofer or Xing VBR methods, most likely CBR (but could be VBR with no header)
2063
			$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = 'cbr';
2064
			if ($recursivesearch) {
2065
				$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = 'vbr';
2066
				if (RecursiveFrameScanning($fd, $ThisFileInfo, $offset, $nextframetestoffset, true)) {
2067
					$recursivesearch = false;
2068
					$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = 'cbr';
2069
				}
2070
				if ($ThisFileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr') {
2071
					$ThisFileInfo['warning'] .= "\n".'VBR file with no VBR header. Bitrate values calculated from actual frame bitrates.';
2072
				}
2073
			}
2074
2075
		}
2076
2077
	}
2078
2079
	if (($ExpectedNumberOfAudioBytes > 0) && ($ExpectedNumberOfAudioBytes != ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']))) {
2080
		if (($ExpectedNumberOfAudioBytes - ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'])) == 1) {
2081
			$ThisFileInfo['warning'] .= "\n".'Last byte of data truncated (this is a known bug in Meracl ID3 Tag Writer before v1.3.5)';
2082
		} elseif ($ExpectedNumberOfAudioBytes > ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'])) {
2083
			$ThisFileInfo['warning'] .= "\n".'Probable truncated file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, only found '.($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']).' (short by '.($ExpectedNumberOfAudioBytes - ($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset'])).' bytes)';
2084
		} else {
2085
			$ThisFileInfo['warning'] .= "\n".'Too much data in file: expecting '.$ExpectedNumberOfAudioBytes.' bytes of audio data, found '.($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']).' ('.(($ThisFileInfo['avdataend'] - $ThisFileInfo['avdataoffset']) - $ExpectedNumberOfAudioBytes).' bytes too many)';
2086
		}
2087
	}
2088
2089
	if (($ThisFileInfo['mpeg']['audio']['bitrate'] == 'free') && empty($ThisFileInfo['audio']['bitrate'])) {
2090
		if (($offset == $ThisFileInfo['avdataoffset']) && empty($ThisFileInfo['mpeg']['audio']['VBR_frames'])) {
2091
			$framebytelength = FreeFormatFrameLength($fd, $offset, $ThisFileInfo, true);
2092
			if ($framebytelength > 0) {
2093
				$ThisFileInfo['mpeg']['audio']['framelength'] = $framebytelength;
2094 View Code Duplication
				if ($ThisFileInfo['mpeg']['audio']['layer'] == 'I') {
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...
2095
					// BitRate = (((FrameLengthInBytes / 4) - Padding) * SampleRate) / 12
2096
					$ThisFileInfo['audio']['bitrate'] = ((($framebytelength / 4) - intval($ThisFileInfo['mpeg']['audio']['padding'])) * $ThisFileInfo['mpeg']['audio']['sample_rate']) / 12;
2097
				} else {
2098
					// Bitrate = ((FrameLengthInBytes - Padding) * SampleRate) / 144
2099
					$ThisFileInfo['audio']['bitrate'] = (($framebytelength - intval($ThisFileInfo['mpeg']['audio']['padding'])) * $ThisFileInfo['mpeg']['audio']['sample_rate']) / 144;
2100
				}
2101
			} else {
2102
				$ThisFileInfo['error'] .= "\n".'Error calculating frame length of free-format MP3 without Xing/LAME header';
2103
			}
2104
		}
2105
	}
2106
2107
	if (($ThisFileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr') && isset($ThisFileInfo['mpeg']['audio']['VBR_frames']) && ($ThisFileInfo['mpeg']['audio']['VBR_frames'] > 1)) {
2108
		$ThisFileInfo['mpeg']['audio']['VBR_frames']--; // don't count the Xing / VBRI frame
2109
		if (($ThisFileInfo['mpeg']['audio']['version'] == '1') && ($ThisFileInfo['mpeg']['audio']['layer'] == 'I')) {
2110
			$ThisFileInfo['mpeg']['audio']['VBR_bitrate'] = ((($ThisFileInfo['mpeg']['audio']['VBR_bytes'] / $ThisFileInfo['mpeg']['audio']['VBR_frames']) * 8) * ($ThisFileInfo['audio']['sample_rate'] / 384)) / 1000;
2111
		} elseif ((($ThisFileInfo['mpeg']['audio']['version'] == '2') || ($ThisFileInfo['mpeg']['audio']['version'] == '2.5')) && ($ThisFileInfo['mpeg']['audio']['layer'] == 'III')) {
2112
			$ThisFileInfo['mpeg']['audio']['VBR_bitrate'] = ((($ThisFileInfo['mpeg']['audio']['VBR_bytes'] / $ThisFileInfo['mpeg']['audio']['VBR_frames']) * 8) * ($ThisFileInfo['audio']['sample_rate'] / 576)) / 1000;
2113
		} else {
2114
			$ThisFileInfo['mpeg']['audio']['VBR_bitrate'] = ((($ThisFileInfo['mpeg']['audio']['VBR_bytes'] / $ThisFileInfo['mpeg']['audio']['VBR_frames']) * 8) * ($ThisFileInfo['audio']['sample_rate'] / 1152)) / 1000;
2115
		}
2116 View Code Duplication
		if ($ThisFileInfo['mpeg']['audio']['VBR_bitrate'] > 0) {
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...
2117
			$ThisFileInfo['audio']['bitrate']         = 1000 * $ThisFileInfo['mpeg']['audio']['VBR_bitrate'];
2118
			$ThisFileInfo['mpeg']['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['VBR_bitrate']; // to avoid confusion
2119
		}
2120
	}
2121
2122
	// End variable-bitrate headers
2123
	////////////////////////////////////////////////////////////////////////////////////
2124
2125
	if ($recursivesearch) {
2126
2127
		if (!RecursiveFrameScanning($fd, $ThisFileInfo, $offset, $nextframetestoffset, $ScanAsCBR)) {
2128
			return false;
2129
		}
2130
2131
	}
2132
2133
2134
	//if (false) {
2135
	//	// experimental side info parsing section - not returning anything useful yet
2136
	//
2137
	//	$SideInfoBitstream = BigEndian2Bin($SideInfoData);
2138
	//	$SideInfoOffset = 0;
2139
	//
2140
	//	if ($ThisFileInfo['mpeg']['audio']['version'] == '1') {
2141
	//		if ($ThisFileInfo['mpeg']['audio']['channelmode'] == 'mono') {
2142
	//			// MPEG-1 (mono)
2143
	//			$ThisFileInfo['mpeg']['audio']['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 9);
2144
	//			$SideInfoOffset += 9;
2145
	//			$SideInfoOffset += 5;
2146
	//		} else {
2147
	//			// MPEG-1 (stereo, joint-stereo, dual-channel)
2148
	//			$ThisFileInfo['mpeg']['audio']['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 9);
2149
	//			$SideInfoOffset += 9;
2150
	//			$SideInfoOffset += 3;
2151
	//		}
2152
	//	} else { // 2 or 2.5
2153
	//		if ($ThisFileInfo['mpeg']['audio']['channelmode'] == 'mono') {
2154
	//			// MPEG-2, MPEG-2.5 (mono)
2155
	//			$ThisFileInfo['mpeg']['audio']['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 8);
2156
	//			$SideInfoOffset += 8;
2157
	//			$SideInfoOffset += 1;
2158
	//		} else {
2159
	//			// MPEG-2, MPEG-2.5 (stereo, joint-stereo, dual-channel)
2160
	//			$ThisFileInfo['mpeg']['audio']['side_info']['main_data_begin'] = substr($SideInfoBitstream, $SideInfoOffset, 8);
2161
	//			$SideInfoOffset += 8;
2162
	//			$SideInfoOffset += 2;
2163
	//		}
2164
	//	}
2165
	//
2166
	//	if ($ThisFileInfo['mpeg']['audio']['version'] == '1') {
2167
	//		for ($channel = 0; $channel < $ThisFileInfo['audio']['channels']; $channel++) {
2168
	//			for ($scfsi_band = 0; $scfsi_band < 4; $scfsi_band++) {
2169
	//				$ThisFileInfo['mpeg']['audio']['scfsi'][$channel][$scfsi_band] = substr($SideInfoBitstream, $SideInfoOffset, 1);
2170
	//				$SideInfoOffset += 2;
2171
	//			}
2172
	//		}
2173
	//	}
2174
	//	for ($granule = 0; $granule < (($ThisFileInfo['mpeg']['audio']['version'] == '1') ? 2 : 1); $granule++) {
2175
	//		for ($channel = 0; $channel < $ThisFileInfo['audio']['channels']; $channel++) {
2176
	//			$ThisFileInfo['mpeg']['audio']['part2_3_length'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 12);
2177
	//			$SideInfoOffset += 12;
2178
	//			$ThisFileInfo['mpeg']['audio']['big_values'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 9);
2179
	//			$SideInfoOffset += 9;
2180
	//			$ThisFileInfo['mpeg']['audio']['global_gain'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 8);
2181
	//			$SideInfoOffset += 8;
2182
	//			if ($ThisFileInfo['mpeg']['audio']['version'] == '1') {
2183
	//				$ThisFileInfo['mpeg']['audio']['scalefac_compress'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 4);
2184
	//				$SideInfoOffset += 4;
2185
	//			} else {
2186
	//				$ThisFileInfo['mpeg']['audio']['scalefac_compress'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 9);
2187
	//				$SideInfoOffset += 9;
2188
	//			}
2189
	//			$ThisFileInfo['mpeg']['audio']['window_switching_flag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
2190
	//			$SideInfoOffset += 1;
2191
	//
2192
	//			if ($ThisFileInfo['mpeg']['audio']['window_switching_flag'][$granule][$channel] == '1') {
2193
	//
2194
	//				$ThisFileInfo['mpeg']['audio']['block_type'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 2);
2195
	//				$SideInfoOffset += 2;
2196
	//				$ThisFileInfo['mpeg']['audio']['mixed_block_flag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
2197
	//				$SideInfoOffset += 1;
2198
	//
2199
	//				for ($region = 0; $region < 2; $region++) {
2200
	//					$ThisFileInfo['mpeg']['audio']['table_select'][$granule][$channel][$region] = substr($SideInfoBitstream, $SideInfoOffset, 5);
2201
	//					$SideInfoOffset += 5;
2202
	//				}
2203
	//				$ThisFileInfo['mpeg']['audio']['table_select'][$granule][$channel][2] = 0;
2204
	//
2205
	//				for ($window = 0; $window < 3; $window++) {
2206
	//					$ThisFileInfo['mpeg']['audio']['subblock_gain'][$granule][$channel][$window] = substr($SideInfoBitstream, $SideInfoOffset, 3);
2207
	//					$SideInfoOffset += 3;
2208
	//				}
2209
	//
2210
	//			} else {
2211
	//
2212
	//				for ($region = 0; $region < 3; $region++) {
2213
	//					$ThisFileInfo['mpeg']['audio']['table_select'][$granule][$channel][$region] = substr($SideInfoBitstream, $SideInfoOffset, 5);
2214
	//					$SideInfoOffset += 5;
2215
	//				}
2216
	//
2217
	//				$ThisFileInfo['mpeg']['audio']['region0_count'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 4);
2218
	//				$SideInfoOffset += 4;
2219
	//				$ThisFileInfo['mpeg']['audio']['region1_count'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 3);
2220
	//				$SideInfoOffset += 3;
2221
	//				$ThisFileInfo['mpeg']['audio']['block_type'][$granule][$channel] = 0;
2222
	//			}
2223
	//
2224
	//			if ($ThisFileInfo['mpeg']['audio']['version'] == '1') {
2225
	//				$ThisFileInfo['mpeg']['audio']['preflag'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
2226
	//				$SideInfoOffset += 1;
2227
	//			}
2228
	//			$ThisFileInfo['mpeg']['audio']['scalefac_scale'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
2229
	//			$SideInfoOffset += 1;
2230
	//			$ThisFileInfo['mpeg']['audio']['count1table_select'][$granule][$channel] = substr($SideInfoBitstream, $SideInfoOffset, 1);
2231
	//			$SideInfoOffset += 1;
2232
	//		}
2233
	//	}
2234
	//}
2235
2236
	return true;
2237
}
2238
2239
function RecursiveFrameScanning(&$fd, &$ThisFileInfo, &$offset, &$nextframetestoffset, $ScanAsCBR) {
2240
	for ($i = 0; $i < MPEG_VALID_CHECK_FRAMES; $i++) {
2241
		// check next MPEG_VALID_CHECK_FRAMES frames for validity, to make sure we haven't run across a false synch
2242
		if (($nextframetestoffset + 4) >= $ThisFileInfo['avdataend']) {
2243
			// end of file
2244
			return true;
2245
		}
2246
2247
		$nextframetestarray = array('error'=>'', 'warning'=>'', 'avdataend'=>$ThisFileInfo['avdataend'], 'avdataoffset'=>$ThisFileInfo['avdataoffset']);
2248
		if (decodeMPEGaudioHeader($fd, $nextframetestoffset, $nextframetestarray, false)) {
2249 View Code Duplication
			if ($ScanAsCBR) {
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...
2250
				// force CBR mode, used for trying to pick out invalid audio streams with
2251
				// valid(?) VBR headers, or VBR streams with no VBR header
2252
				if (!isset($nextframetestarray['mpeg']['audio']['bitrate']) || !isset($ThisFileInfo['mpeg']['audio']['bitrate']) || ($nextframetestarray['mpeg']['audio']['bitrate'] != $ThisFileInfo['mpeg']['audio']['bitrate'])) {
2253
					return false;
2254
				}
2255
			}
2256
2257
2258
			// next frame is OK, get ready to check the one after that
2259
			if (isset($nextframetestarray['mpeg']['audio']['framelength']) && ($nextframetestarray['mpeg']['audio']['framelength'] > 0)) {
2260
				$nextframetestoffset += $nextframetestarray['mpeg']['audio']['framelength'];
2261
			} else {
2262
				$ThisFileInfo['error'] .= "\n".'Frame at offset ('.$offset.') is has an invalid frame length.';
2263
				return false;
2264
			}
2265
2266
		} else {
2267
2268
			// next frame is not valid, note the error and fail, so scanning can contiue for a valid frame sequence
2269
			$ThisFileInfo['error'] .= "\n".'Frame at offset ('.$offset.') is valid, but the next one at ('.$nextframetestoffset.') is not.';
2270
2271
			return false;
2272
		}
2273
	}
2274
	return true;
2275
}
2276
2277
function FreeFormatFrameLength($fd, $offset, &$ThisFileInfo, $deepscan=false) {
2278
	fseek($fd, $offset, SEEK_SET);
2279
	$MPEGaudioData = fread($fd, 32768);
2280
2281
	$SyncPattern1 = substr($MPEGaudioData, 0, 4);
2282
	// may be different pattern due to padding
2283
	$SyncPattern2 = $SyncPattern1[0].$SyncPattern1[1].chr(ord($SyncPattern1[2]) | 0x02).$SyncPattern1[3];
2284 View Code Duplication
	if ($SyncPattern2 === $SyncPattern1) {
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...
2285
		$SyncPattern2 = $SyncPattern1[0].$SyncPattern1[1].chr(ord($SyncPattern1[2]) & 0xFD).$SyncPattern1[3];
2286
	}
2287
2288
	$framelength = false;
2289
	$framelength1 = strpos($MPEGaudioData, $SyncPattern1, 4);
2290
	$framelength2 = strpos($MPEGaudioData, $SyncPattern2, 4);
2291
	if ($framelength1 > 4) {
2292
		$framelength = $framelength1;
2293
	}
2294
	if (($framelength2 > 4) && ($framelength2 < $framelength1)) {
2295
		$framelength = $framelength2;
2296
	}
2297
	if (!$framelength) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $framelength of type integer|false is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2298
2299
		// LAME 3.88 has a different value for modeextension on the first frame vs the rest
2300
		$framelength1 = strpos($MPEGaudioData, substr($SyncPattern1, 0, 3), 4);
2301
		$framelength2 = strpos($MPEGaudioData, substr($SyncPattern2, 0, 3), 4);
2302
2303
		if ($framelength1 > 4) {
2304
			$framelength = $framelength1;
2305
		}
2306
		if (($framelength2 > 4) && ($framelength2 < $framelength1)) {
2307
			$framelength = $framelength2;
2308
		}
2309
		if (!$framelength) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $framelength of type integer|false is loosely compared to false; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
2310
			$ThisFileInfo['error'] .= "\n".'Cannot find next free-format synch pattern ('.PrintHexBytes($SyncPattern1).' or '.PrintHexBytes($SyncPattern2).') after offset '.$offset;
2311
			return false;
2312
		} else {
2313
			$ThisFileInfo['warning'] .= "\n".'ModeExtension varies between first frame and other frames (known free-format issue in LAME 3.88)';
2314
			$ThisFileInfo['audio']['codec']   = 'LAME';
2315
			$ThisFileInfo['audio']['encoder'] = 'LAME3.88';
2316
			$SyncPattern1 = substr($SyncPattern1, 0, 3);
2317
			$SyncPattern2 = substr($SyncPattern2, 0, 3);
2318
		}
2319
	}
2320
2321
	if ($deepscan) {
2322
2323
		$ActualFrameLengthValues = array();
2324
		$nextoffset = $offset + $framelength;
2325
		while ($nextoffset < ($ThisFileInfo['avdataend'] - 6)) {
2326
			fseek($fd, $nextoffset - 1, SEEK_SET);
2327
			$NextSyncPattern = fread($fd, 6);
2328
			if ((substr($NextSyncPattern, 1, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 1, strlen($SyncPattern2)) == $SyncPattern2)) {
2329
				// good - found where expected
2330
				$ActualFrameLengthValues[] = $framelength;
2331 View Code Duplication
			} elseif ((substr($NextSyncPattern, 0, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 0, strlen($SyncPattern2)) == $SyncPattern2)) {
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...
2332
				// ok - found one byte earlier than expected (last frame wasn't padded, first frame was)
2333
				$ActualFrameLengthValues[] = ($framelength - 1);
2334
				$nextoffset--;
2335
			} elseif ((substr($NextSyncPattern, 2, strlen($SyncPattern1)) == $SyncPattern1) || (substr($NextSyncPattern, 2, strlen($SyncPattern2)) == $SyncPattern2)) {
2336
				// ok - found one byte later than expected (last frame was padded, first frame wasn't)
2337
				$ActualFrameLengthValues[] = ($framelength + 1);
2338
				$nextoffset++;
2339
			} else {
2340
				$ThisFileInfo['error'] .= "\n".'Did not find expected free-format sync pattern at offset '.$nextoffset;
2341
				return false;
2342
			}
2343
			$nextoffset += $framelength;
2344
		}
2345 View Code Duplication
		if (count($ActualFrameLengthValues) > 0) {
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...
2346
			$framelength = round(array_sum($ActualFrameLengthValues) / count($ActualFrameLengthValues));
2347
		}
2348
	}
2349
	return $framelength;
2350
}
2351
2352
2353
function getOnlyMPEGaudioInfo($fd, &$ThisFileInfo, $avdataoffset, $BitrateHistogram=false) {
2354
	// looks for synch, decodes MPEG audio header
2355
2356
	fseek($fd, $avdataoffset, SEEK_SET);
2357
	$header = '';
2358
	$SynchSeekOffset = 0;
2359
2360
	if (!defined('CONST_FF')) {
2361
		define('CONST_FF', chr(0xFF));
2362
		define('CONST_E0', chr(0xE0));
2363
	}
2364
2365
	static $MPEGaudioVersionLookup;
2366
	static $MPEGaudioLayerLookup;
2367
	static $MPEGaudioBitrateLookup;
2368
	if (empty($MPEGaudioVersionLookup)) {
2369
		$MPEGaudioVersionLookup = MPEGaudioVersionArray();
2370
		$MPEGaudioLayerLookup   = MPEGaudioLayerArray();
2371
		$MPEGaudioBitrateLookup = MPEGaudioBitrateArray();
2372
2373
	}
2374
2375
	$header_len = strlen($header) - round(32768 / 2);
2376
	while (true) {
2377
2378
		if (($SynchSeekOffset > $header_len) && (($avdataoffset + $SynchSeekOffset)  < $ThisFileInfo['avdataend']) && !feof($fd)) {
2379
2380
			if ($SynchSeekOffset > 131072) {
2381
				// if a synch's not found within the first 128k bytes, then give up
2382
				$ThisFileInfo['error'] .= "\n".'could not find valid MPEG synch within the first 131072 bytes';
2383
				if (isset($ThisFileInfo['audio']['bitrate'])) {
2384
					unset($ThisFileInfo['audio']['bitrate']);
2385
				}
2386
				if (isset($ThisFileInfo['mpeg']['audio'])) {
2387
					unset($ThisFileInfo['mpeg']['audio']);
2388
				}
2389 View Code Duplication
				if (isset($ThisFileInfo['mpeg']) && (!is_array($ThisFileInfo['mpeg']) || (count($ThisFileInfo['mpeg']) == 0))) {
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...
2390
					unset($ThisFileInfo['mpeg']);
2391
				}
2392
				return false;
2393
2394
			} elseif ($header .= fread($fd, 32768)) {
2395
2396
				// great
2397
				$header_len = strlen($header) - round(32768 / 2);
2398
2399
			} else {
2400
2401
				$ThisFileInfo['error'] .= "\n".'could not find valid MPEG synch before end of file';
2402
				if (isset($ThisFileInfo['audio']['bitrate'])) {
2403
					unset($ThisFileInfo['audio']['bitrate']);
2404
				}
2405
				if (isset($ThisFileInfo['mpeg']['audio'])) {
2406
					unset($ThisFileInfo['mpeg']['audio']);
2407
				}
2408 View Code Duplication
				if (isset($ThisFileInfo['mpeg']) && (!is_array($ThisFileInfo['mpeg']) || (count($ThisFileInfo['mpeg']) == 0))) {
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...
2409
					unset($ThisFileInfo['mpeg']);
2410
				}
2411
				return false;
2412
2413
			}
2414
		}
2415
2416
		if (($SynchSeekOffset + 1) >= strlen($header)) {
2417
			$ThisFileInfo['error'] .= "\n".'could not find valid MPEG synch before end of file';
2418
			return false;
2419
		}
2420
2421
		if (($header[$SynchSeekOffset] == CONST_FF) && ($header[($SynchSeekOffset + 1)] > CONST_E0)) { // synch detected
2422
2423 View Code Duplication
			if (!isset($FirstFrameThisfileInfo) && !isset($ThisFileInfo['mpeg']['audio'])) {
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...
2424
				$FirstFrameThisfileInfo = $ThisFileInfo;
2425
				$FirstFrameAVDataOffset = $avdataoffset + $SynchSeekOffset;
2426
				if (!decodeMPEGaudioHeader($fd, $avdataoffset + $SynchSeekOffset, $FirstFrameThisfileInfo, false)) {
2427
					// if this is the first valid MPEG-audio frame, save it in case it's a VBR header frame and there's
2428
					// garbage between this frame and a valid sequence of MPEG-audio frames, to be restored below
2429
					unset($FirstFrameThisfileInfo);
2430
				}
2431
			}
2432
			$dummy = $ThisFileInfo; // only overwrite real data if valid header found
2433
2434
			if (decodeMPEGaudioHeader($fd, $avdataoffset + $SynchSeekOffset, $dummy, true)) {
2435
2436
				$ThisFileInfo = $dummy;
2437
				$ThisFileInfo['avdataoffset'] = $avdataoffset + $SynchSeekOffset;
2438 View Code Duplication
				switch ($ThisFileInfo['fileformat']) {
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...
2439
					case '':
2440
					case 'id3':
2441
					case 'ape':
2442
					case 'mp3':
2443
						$ThisFileInfo['fileformat']               = 'mp3';
2444
						$ThisFileInfo['audio']['dataformat']      = 'mp3';
2445
				}
2446
				if (isset($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode']) && ($FirstFrameThisfileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr')) {
2447
					if (!CloseMatch($ThisFileInfo['audio']['bitrate'], $FirstFrameThisfileInfo['audio']['bitrate'], 1)) {
2448
						// If there is garbage data between a valid VBR header frame and a sequence
2449
						// of valid MPEG-audio frames the VBR data is no longer discarded.
2450
						$ThisFileInfo = $FirstFrameThisfileInfo;
2451
						$ThisFileInfo['avdataoffset']        = $FirstFrameAVDataOffset;
0 ignored issues
show
Bug introduced by
The variable $FirstFrameAVDataOffset does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
2452
						$ThisFileInfo['fileformat']          = 'mp3';
2453
						$ThisFileInfo['audio']['dataformat'] = 'mp3';
2454
						$dummy                               = $ThisFileInfo;
2455
						unset($dummy['mpeg']['audio']);
2456
						$GarbageOffsetStart = $FirstFrameAVDataOffset + $FirstFrameThisfileInfo['mpeg']['audio']['framelength'];
2457
						$GarbageOffsetEnd   = $avdataoffset + $SynchSeekOffset;
2458
						if (decodeMPEGaudioHeader($fd, $GarbageOffsetEnd, $dummy, true, true)) {
2459
2460
							$ThisFileInfo = $dummy;
2461
							$ThisFileInfo['avdataoffset'] = $GarbageOffsetEnd;
2462
							$ThisFileInfo['warning'] .= "\n".'apparently-valid VBR header not used because could not find '.MPEG_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.'), but did find valid CBR stream starting at '.$GarbageOffsetEnd;
2463
2464
						} else {
2465
2466
							$ThisFileInfo['warning'] .= "\n".'using data from VBR header even though could not find '.MPEG_VALID_CHECK_FRAMES.' consecutive MPEG-audio frames immediately after VBR header (garbage data for '.($GarbageOffsetEnd - $GarbageOffsetStart).' bytes between '.$GarbageOffsetStart.' and '.$GarbageOffsetEnd.')';
2467
2468
						}
2469
					}
2470
				}
2471
2472 View Code Duplication
				if (isset($ThisFileInfo['mpeg']['audio']['bitrate_mode']) && ($ThisFileInfo['mpeg']['audio']['bitrate_mode'] == 'vbr') && !isset($ThisFileInfo['mpeg']['audio']['VBR_method'])) {
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...
2473
					// VBR file with no VBR header
2474
					$BitrateHistogram = true;
2475
				}
2476
2477
				if ($BitrateHistogram) {
2478
2479
					$ThisFileInfo['mpeg']['audio']['stereo_distribution']  = array('stereo'=>0, 'joint stereo'=>0, 'dual channel'=>0, 'mono'=>0);
2480
					$ThisFileInfo['mpeg']['audio']['version_distribution'] = array('1'=>0, '2'=>0, '2.5'=>0);
2481
2482 View Code Duplication
					if ($ThisFileInfo['mpeg']['audio']['version'] == '1') {
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...
2483
						if ($ThisFileInfo['mpeg']['audio']['layer'] == 'III') {
2484
							$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32=>0, 40=>0, 48=>0, 56=>0, 64=>0, 80=>0, 96=>0, 112=>0, 128=>0, 160=>0, 192=>0, 224=>0, 256=>0, 320=>0);
2485
						} elseif ($ThisFileInfo['mpeg']['audio']['layer'] == 'II') {
2486
							$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32=>0, 48=>0, 56=>0, 64=>0, 80=>0, 96=>0, 112=>0, 128=>0, 160=>0, 192=>0, 224=>0, 256=>0, 320=>0, 384=>0);
2487
						} elseif ($ThisFileInfo['mpeg']['audio']['layer'] == 'I') {
2488
							$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32=>0, 64=>0, 96=>0, 128=>0, 160=>0, 192=>0, 224=>0, 256=>0, 288=>0, 320=>0, 352=>0, 384=>0, 416=>0, 448=>0);
2489
						}
2490
					} elseif ($ThisFileInfo['mpeg']['audio']['layer'] == 'I') {
2491
						$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 32=>0, 48=>0, 56=>0, 64=>0, 80=>0, 96=>0, 112=>0, 128=>0, 144=>0, 160=>0, 176=>0, 192=>0, 224=>0, 256=>0);
2492
					} else {
2493
						$ThisFileInfo['mpeg']['audio']['bitrate_distribution'] = array('free'=>0, 8=>0, 16=>0, 24=>0, 32=>0, 40=>0, 48=>0, 56=>0, 64=>0, 80=>0, 96=>0, 112=>0, 128=>0, 144=>0, 160=>0);
2494
					}
2495
2496
					$dummy = array('error'=>$ThisFileInfo['error'], 'warning'=>$ThisFileInfo['warning'], 'avdataend'=>$ThisFileInfo['avdataend'], 'avdataoffset'=>$ThisFileInfo['avdataoffset']);
2497
					$synchstartoffset = $ThisFileInfo['avdataoffset'];
2498
2499
					$FastMode = false;
2500
					while (decodeMPEGaudioHeader($fd, $synchstartoffset, $dummy, false, false, $FastMode)) {
2501
						$FastMode = true;
2502
						$thisframebitrate = $MPEGaudioBitrateLookup[$MPEGaudioVersionLookup[$dummy['mpeg']['audio']['raw']['version']]][$MPEGaudioLayerLookup[$dummy['mpeg']['audio']['raw']['layer']]][$dummy['mpeg']['audio']['raw']['bitrate']];
2503
2504
						$ThisFileInfo['mpeg']['audio']['bitrate_distribution'][$thisframebitrate]++;
2505
						$ThisFileInfo['mpeg']['audio']['stereo_distribution'][$dummy['mpeg']['audio']['channelmode']]++;
2506
						$ThisFileInfo['mpeg']['audio']['version_distribution'][$dummy['mpeg']['audio']['version']]++;
2507
						if (empty($dummy['mpeg']['audio']['framelength'])) {
2508
							$ThisFileInfo['warning'] .= "\n".'Invalid/missing framelength in histogram analysis - aborting';
2509
$synchstartoffset += 4;
2510
//							return false;
2511
						}
2512
						$synchstartoffset += $dummy['mpeg']['audio']['framelength'];
2513
					}
2514
2515
					$bittotal     = 0;
2516
					$framecounter = 0;
2517 View Code Duplication
					foreach ($ThisFileInfo['mpeg']['audio']['bitrate_distribution'] as $bitratevalue => $bitratecount) {
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...
2518
						$framecounter += $bitratecount;
2519
						if ($bitratevalue != 'free') {
2520
							$bittotal += ($bitratevalue * $bitratecount);
2521
						}
2522
					}
2523
					if ($framecounter == 0) {
2524
						$ThisFileInfo['error'] .= "\n".'Corrupt MP3 file: framecounter == zero';
2525
						return false;
2526
					}
2527
					$ThisFileInfo['mpeg']['audio']['frame_count'] = $framecounter;
2528
					$ThisFileInfo['mpeg']['audio']['bitrate']     = 1000 * ($bittotal / $framecounter);
2529
2530
					$ThisFileInfo['audio']['bitrate'] = $ThisFileInfo['mpeg']['audio']['bitrate'];
2531
2532
2533
					// Definitively set VBR vs CBR, even if the Xing/LAME/VBRI header says differently
2534
					$distinct_bitrates = 0;
2535 View Code Duplication
					foreach ($ThisFileInfo['mpeg']['audio']['bitrate_distribution'] as $bitrate_value => $bitrate_count) {
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...
2536
						if ($bitrate_count > 0) {
2537
							$distinct_bitrates++;
2538
						}
2539
					}
2540
					if ($distinct_bitrates > 1) {
2541
						$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = 'vbr';
2542
					} else {
2543
						$ThisFileInfo['mpeg']['audio']['bitrate_mode'] = 'cbr';
2544
					}
2545
					$ThisFileInfo['audio']['bitrate_mode'] = $ThisFileInfo['mpeg']['audio']['bitrate_mode'];
2546
2547
				}
2548
2549
				break; // exit while()
2550
			}
2551
		}
2552
2553
		$SynchSeekOffset++;
2554
		if (($avdataoffset + $SynchSeekOffset) >= $ThisFileInfo['avdataend']) {
2555
			// end of file/data
2556
2557
			if (empty($ThisFileInfo['mpeg']['audio'])) {
2558
2559
				$ThisFileInfo['error'] .= "\n".'could not find valid MPEG synch before end of file';
2560
				if (isset($ThisFileInfo['audio']['bitrate'])) {
2561
					unset($ThisFileInfo['audio']['bitrate']);
2562
				}
2563
				if (isset($ThisFileInfo['mpeg']['audio'])) {
2564
					unset($ThisFileInfo['mpeg']['audio']);
2565
				}
2566 View Code Duplication
				if (isset($ThisFileInfo['mpeg']) && (!is_array($ThisFileInfo['mpeg']) || empty($ThisFileInfo['mpeg']))) {
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...
2567
					unset($ThisFileInfo['mpeg']);
2568
				}
2569
				return false;
2570
2571
			}
2572
			break;
2573
		}
2574
2575
	}
2576
	$ThisFileInfo['audio']['bits_per_sample'] = 16;
2577
	$ThisFileInfo['audio']['channels']        = $ThisFileInfo['mpeg']['audio']['channels'];
2578
	$ThisFileInfo['audio']['channelmode']     = $ThisFileInfo['mpeg']['audio']['channelmode'];
2579
	$ThisFileInfo['audio']['sample_rate']     = $ThisFileInfo['mpeg']['audio']['sample_rate'];
2580
	return true;
2581
}
2582
2583
2584
function MPEGaudioVersionArray() {
2585
	static $MPEGaudioVersion = array('2.5', false, '2', '1');
2586
	return $MPEGaudioVersion;
2587
}
2588
2589
function MPEGaudioLayerArray() {
2590
	static $MPEGaudioLayer = array(false, 'III', 'II', 'I');
2591
	return $MPEGaudioLayer;
2592
}
2593
2594
function MPEGaudioBitrateArray() {
2595
	static $MPEGaudioBitrate;
2596
	if (empty($MPEGaudioBitrate)) {
2597
		$MPEGaudioBitrate['1']['I']     = array('free', 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448);
2598
		$MPEGaudioBitrate['1']['II']    = array('free', 32, 48, 56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320, 384);
2599
		$MPEGaudioBitrate['1']['III']   = array('free', 32, 40, 48,  56,  64,  80,  96, 112, 128, 160, 192, 224, 256, 320);
2600
		$MPEGaudioBitrate['2']['I']     = array('free', 32, 48, 56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256);
2601
		$MPEGaudioBitrate['2']['II']    = array('free',  8, 16, 24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160);
2602
		$MPEGaudioBitrate['2']['III']   = $MPEGaudioBitrate['2']['II'];
2603
		$MPEGaudioBitrate['2.5']['I']   = $MPEGaudioBitrate['2']['I'];
2604
		$MPEGaudioBitrate['2.5']['II']  = $MPEGaudioBitrate['2']['II'];
2605
		$MPEGaudioBitrate['2.5']['III'] = $MPEGaudioBitrate['2']['III'];
2606
	}
2607
	return $MPEGaudioBitrate;
2608
}
2609
2610
function MPEGaudioFrequencyArray() {
2611
	static $MPEGaudioFrequency;
2612
	if (empty($MPEGaudioFrequency)) {
2613
		$MPEGaudioFrequency['1']   = array(44100, 48000, 32000);
2614
		$MPEGaudioFrequency['2']   = array(22050, 24000, 16000);
2615
		$MPEGaudioFrequency['2.5'] = array(11025, 12000,  8000);
2616
	}
2617
	return $MPEGaudioFrequency;
2618
}
2619
2620
function MPEGaudioChannelModeArray() {
2621
	static $MPEGaudioChannelMode = array('stereo', 'joint stereo', 'dual channel', 'mono');
2622
	return $MPEGaudioChannelMode;
2623
}
2624
2625
function MPEGaudioModeExtensionArray() {
2626
	static $MPEGaudioModeExtension;
2627
	if (empty($MPEGaudioModeExtension)) {
2628
		$MPEGaudioModeExtension['I']   = array('4-31', '8-31', '12-31', '16-31');
2629
		$MPEGaudioModeExtension['II']  = array('4-31', '8-31', '12-31', '16-31');
2630
		$MPEGaudioModeExtension['III'] = array('', 'IS', 'MS', 'IS+MS');
2631
	}
2632
	return $MPEGaudioModeExtension;
2633
}
2634
2635
function MPEGaudioEmphasisArray() {
2636
	static $MPEGaudioEmphasis = array('none', '50/15ms', false, 'CCIT J.17');
2637
	return $MPEGaudioEmphasis;
2638
}
2639
2640
2641
function MPEGaudioHeaderBytesValid($head4) {
2642
	return MPEGaudioHeaderValid(MPEGaudioHeaderDecode($head4));
2643
}
2644
2645
function MPEGaudioHeaderValid($rawarray, $echoerrors=false) {
2646
2647
	if (($rawarray['synch'] & 0x0FFE) != 0x0FFE) {
2648
		return false;
2649
	}
2650
2651
	static $MPEGaudioVersionLookup;
2652
	static $MPEGaudioLayerLookup;
2653
	static $MPEGaudioBitrateLookup;
2654
	static $MPEGaudioFrequencyLookup;
2655
	static $MPEGaudioChannelModeLookup;
2656
	static $MPEGaudioModeExtensionLookup;
2657
	static $MPEGaudioEmphasisLookup;
2658 View Code Duplication
	if (empty($MPEGaudioVersionLookup)) {
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...
2659
		$MPEGaudioVersionLookup       = MPEGaudioVersionArray();
2660
		$MPEGaudioLayerLookup         = MPEGaudioLayerArray();
2661
		$MPEGaudioBitrateLookup       = MPEGaudioBitrateArray();
2662
		$MPEGaudioFrequencyLookup     = MPEGaudioFrequencyArray();
2663
		$MPEGaudioChannelModeLookup   = MPEGaudioChannelModeArray();
2664
		$MPEGaudioModeExtensionLookup = MPEGaudioModeExtensionArray();
2665
		$MPEGaudioEmphasisLookup      = MPEGaudioEmphasisArray();
2666
	}
2667
2668
	if (isset($MPEGaudioVersionLookup[$rawarray['version']])) {
2669
		$decodedVersion = $MPEGaudioVersionLookup[$rawarray['version']];
2670
	} else {
2671
		if ($echoerrors) {
2672
			echo "\n".'invalid Version ('.$rawarray['version'].')';
2673
		}
2674
		return false;
2675
	}
2676
	if (isset($MPEGaudioLayerLookup[$rawarray['layer']])) {
2677
		$decodedLayer = $MPEGaudioLayerLookup[$rawarray['layer']];
2678
	} else {
2679
		if ($echoerrors) {
2680
			echo "\n".'invalid Layer ('.$rawarray['layer'].')';
2681
		}
2682
		return false;
2683
	}
2684 View Code Duplication
	if (!isset($MPEGaudioBitrateLookup[$decodedVersion][$decodedLayer][$rawarray['bitrate']])) {
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...
2685
		if ($echoerrors) {
2686
			echo "\n".'invalid Bitrate ('.$rawarray['bitrate'].')';
2687
		}
2688
		if ($rawarray['bitrate'] == 15) {
2689
			// known issue in LAME 3.90 - 3.93.1 where free-format has bitrate ID of 15 instead of 0
2690
			// let it go through here otherwise file will not be identified
2691
		} else {
2692
			return false;
2693
		}
2694
	}
2695 View Code Duplication
	if (!isset($MPEGaudioFrequencyLookup[$decodedVersion][$rawarray['sample_rate']])) {
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...
2696
		if ($echoerrors) {
2697
			echo "\n".'invalid Frequency ('.$rawarray['sample_rate'].')';
2698
		}
2699
		return false;
2700
	}
2701 View Code Duplication
	if (!isset($MPEGaudioChannelModeLookup[$rawarray['channelmode']])) {
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...
2702
		if ($echoerrors) {
2703
			echo "\n".'invalid ChannelMode ('.$rawarray['channelmode'].')';
2704
		}
2705
		return false;
2706
	}
2707 View Code Duplication
	if (!isset($MPEGaudioModeExtensionLookup[$decodedLayer][$rawarray['modeextension']])) {
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...
2708
		if ($echoerrors) {
2709
			echo "\n".'invalid Mode Extension ('.$rawarray['modeextension'].')';
2710
		}
2711
		return false;
2712
	}
2713 View Code Duplication
	if (!isset($MPEGaudioEmphasisLookup[$rawarray['emphasis']])) {
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...
2714
		if ($echoerrors) {
2715
			echo "\n".'invalid Emphasis ('.$rawarray['emphasis'].')';
2716
		}
2717
		return false;
2718
	}
2719
	// These are just either set or not set, you can't mess that up :)
2720
	// $rawarray['protection'];
2721
	// $rawarray['padding'];
2722
	// $rawarray['private'];
2723
	// $rawarray['copyright'];
2724
	// $rawarray['original'];
2725
2726
	return true;
2727
}
2728
2729 View Code Duplication
function MPEGaudioHeaderDecode($Header4Bytes) {
0 ignored issues
show
Duplication introduced by
This function 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...
2730
	// AAAA AAAA  AAAB BCCD  EEEE FFGH  IIJJ KLMM
2731
	// A - Frame sync (all bits set)
2732
	// B - MPEG Audio version ID
2733
	// C - Layer description
2734
	// D - Protection bit
2735
	// E - Bitrate index
2736
	// F - Sampling rate frequency index
2737
	// G - Padding bit
2738
	// H - Private bit
2739
	// I - Channel Mode
2740
	// J - Mode extension (Only if Joint stereo)
2741
	// K - Copyright
2742
	// L - Original
2743
	// M - Emphasis
2744
2745
	if (strlen($Header4Bytes) != 4) {
2746
		return false;
2747
	}
2748
2749
	$MPEGrawHeader['synch']         = (BigEndian2Int(substr($Header4Bytes, 0, 2)) & 0xFFE0) >> 4;
0 ignored issues
show
Coding Style Comprehensibility introduced by
$MPEGrawHeader was never initialized. Although not strictly required by PHP, it is generally a good practice to add $MPEGrawHeader = 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...
2750
	$MPEGrawHeader['version']       = (ord($Header4Bytes[1]) & 0x18) >> 3; //    BB
2751
	$MPEGrawHeader['layer']         = (ord($Header4Bytes[1]) & 0x06) >> 1; //      CC
2752
	$MPEGrawHeader['protection']    = (ord($Header4Bytes[1]) & 0x01);      //        D
2753
	$MPEGrawHeader['bitrate']       = (ord($Header4Bytes[2]) & 0xF0) >> 4; // EEEE
2754
	$MPEGrawHeader['sample_rate']   = (ord($Header4Bytes[2]) & 0x0C) >> 2; //     FF
2755
	$MPEGrawHeader['padding']       = (ord($Header4Bytes[2]) & 0x02) >> 1; //       G
2756
	$MPEGrawHeader['private']       = (ord($Header4Bytes[2]) & 0x01);      //        H
2757
	$MPEGrawHeader['channelmode']   = (ord($Header4Bytes[3]) & 0xC0) >> 6; // II
2758
	$MPEGrawHeader['modeextension'] = (ord($Header4Bytes[3]) & 0x30) >> 4; //   JJ
2759
	$MPEGrawHeader['copyright']     = (ord($Header4Bytes[3]) & 0x08) >> 3; //     K
2760
	$MPEGrawHeader['original']      = (ord($Header4Bytes[3]) & 0x04) >> 2; //      L
2761
	$MPEGrawHeader['emphasis']      = (ord($Header4Bytes[3]) & 0x03);      //       MM
2762
2763
	return $MPEGrawHeader;
2764
}
2765
2766
function MPEGaudioFrameLength(&$bitrate, &$version, &$layer, $padding, &$samplerate) {
2767
	static $AudioFrameLengthCache = array();
2768
2769
	if (!isset($AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate])) {
2770
		$AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate] = false;
2771 View Code Duplication
		if ($bitrate != 'free') {
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...
2772
2773
			if ($version == '1') {
2774
2775
				if ($layer == 'I') {
2776
2777
					// For Layer I slot is 32 bits long
2778
					$FrameLengthCoefficient = 48;
2779
					$SlotLength = 4;
2780
2781
				} else { // Layer II / III
2782
2783
					// for Layer II and Layer III slot is 8 bits long.
2784
					$FrameLengthCoefficient = 144;
2785
					$SlotLength = 1;
2786
2787
				}
2788
2789
			} else { // MPEG-2 / MPEG-2.5
2790
2791
				if ($layer == 'I') {
2792
2793
					// For Layer I slot is 32 bits long
2794
					$FrameLengthCoefficient = 24;
2795
					$SlotLength = 4;
2796
2797
				} elseif ($layer == 'II') {
2798
2799
					// for Layer II and Layer III slot is 8 bits long.
2800
					$FrameLengthCoefficient = 144;
2801
					$SlotLength = 1;
2802
2803
				} else { // III
2804
2805
					// for Layer II and Layer III slot is 8 bits long.
2806
					$FrameLengthCoefficient = 72;
2807
					$SlotLength = 1;
2808
2809
				}
2810
2811
			}
2812
2813
			// FrameLengthInBytes = ((Coefficient * BitRate) / SampleRate) + Padding
2814
			// http://66.96.216.160/cgi-bin/YaBB.pl?board=c&action=display&num=1018474068
2815
			// -> [Finding the next frame synch] on www.r3mix.net forums if the above link goes dead
2816
			if ($samplerate > 0) {
2817
				$NewFramelength  = ($FrameLengthCoefficient * $bitrate * 1000) / $samplerate;
2818
				$NewFramelength  = floor($NewFramelength / $SlotLength) * $SlotLength; // round to next-lower multiple of SlotLength (1 byte for Layer II/III, 4 bytes for Layer I)
2819
				if ($padding) {
2820
					$NewFramelength += $SlotLength;
2821
				}
2822
				$AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate] = (int) $NewFramelength;
2823
			}
2824
		}
2825
	}
2826
	return $AudioFrameLengthCache[$bitrate][$version][$layer][$padding][$samplerate];
2827
}
2828
2829 View Code Duplication
function LAMEvbrMethodLookup($VBRmethodID) {
0 ignored issues
show
Duplication introduced by
This function 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...
2830
	static $LAMEvbrMethodLookup = array();
2831
	if (empty($LAMEvbrMethodLookup)) {
2832
		$LAMEvbrMethodLookup[0x00] = 'unknown';
2833
		$LAMEvbrMethodLookup[0x01] = 'cbr';
2834
		$LAMEvbrMethodLookup[0x02] = 'abr';
2835
		$LAMEvbrMethodLookup[0x03] = 'vbr-old / vbr-rh';
2836
		$LAMEvbrMethodLookup[0x04] = 'vbr-mtrh';
2837
		$LAMEvbrMethodLookup[0x05] = 'vbr-new / vbr-mt';
2838
	}
2839
	return (isset($LAMEvbrMethodLookup[$VBRmethodID]) ? $LAMEvbrMethodLookup[$VBRmethodID] : '');
2840
}
2841
2842
function LAMEmiscStereoModeLookup($StereoModeID) {
2843
	static $LAMEmiscStereoModeLookup = array();
2844
	if (empty($LAMEmiscStereoModeLookup)) {
2845
		$LAMEmiscStereoModeLookup[0] = 'mono';
2846
		$LAMEmiscStereoModeLookup[1] = 'stereo';
2847
		$LAMEmiscStereoModeLookup[2] = 'dual';
2848
		$LAMEmiscStereoModeLookup[3] = 'joint';
2849
		$LAMEmiscStereoModeLookup[4] = 'forced';
2850
		$LAMEmiscStereoModeLookup[5] = 'auto';
2851
		$LAMEmiscStereoModeLookup[6] = 'intensity';
2852
		$LAMEmiscStereoModeLookup[7] = 'other';
2853
	}
2854
	return (isset($LAMEmiscStereoModeLookup[$StereoModeID]) ? $LAMEmiscStereoModeLookup[$StereoModeID] : '');
2855
}
2856
2857
function LAMEmiscSourceSampleFrequencyLookup($SourceSampleFrequencyID) {
2858
	static $LAMEmiscSourceSampleFrequencyLookup = array();
2859
	if (empty($LAMEmiscSourceSampleFrequencyLookup)) {
2860
		$LAMEmiscSourceSampleFrequencyLookup[0] = '<= 32 kHz';
2861
		$LAMEmiscSourceSampleFrequencyLookup[1] = '44.1 kHz';
2862
		$LAMEmiscSourceSampleFrequencyLookup[2] = '48 kHz';
2863
		$LAMEmiscSourceSampleFrequencyLookup[3] = '> 48kHz';
2864
	}
2865
	return (isset($LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID]) ? $LAMEmiscSourceSampleFrequencyLookup[$SourceSampleFrequencyID] : '');
2866
}
2867
2868
function LAMEsurroundInfoLookup($SurroundInfoID) {
2869
	static $LAMEsurroundInfoLookup = array();
2870
	if (empty($LAMEsurroundInfoLookup)) {
2871
		$LAMEsurroundInfoLookup[0] = 'no surround info';
2872
		$LAMEsurroundInfoLookup[1] = 'DPL encoding';
2873
		$LAMEsurroundInfoLookup[2] = 'DPL2 encoding';
2874
		$LAMEsurroundInfoLookup[3] = 'Ambisonic encoding';
2875
	}
2876
	return (isset($LAMEsurroundInfoLookup[$SurroundInfoID]) ? $LAMEsurroundInfoLookup[$SurroundInfoID] : 'reserved');
2877
}
2878
2879
for ($i = 0x00; $i <= 0xFF; $i++) {
2880
	$head4 = "\xFF\xFE".chr($i)."\x00";
2881
	$isvalid = MPEGaudioHeaderBytesValid($head4);
2882
	echo '<div style="color: '.($isvalid ? 'green' : 'red').';">'.str_pad(strtoupper(dechex($i)), 2, '0', STR_PAD_LEFT).' = '.htmlentities(chr($i)).' = '.($isvalid ? 'valid' : 'INVALID').'</div>';
2883
}
2884