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

getid3_lib::iconv_fallback()   C

Complexity

Conditions 17
Paths 22

Size

Total Lines 69

Duplication

Lines 16
Ratio 23.19 %

Importance

Changes 0
Metric Value
cc 17
nc 22
nop 3
dl 16
loc 69
rs 5.2166
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/////////////////////////////////////////////////////////////////
4
/// getID3() by James Heinrich <[email protected]>               //
5
//  available at https://github.com/JamesHeinrich/getID3       //
6
//            or https://www.getid3.org                        //
7
//            or http://getid3.sourceforge.net                 //
8
//                                                             //
9
// getid3.lib.php - part of getID3()                           //
10
//  see readme.txt for more details                            //
11
//                                                            ///
12
/////////////////////////////////////////////////////////////////
13
14
15
class getid3_lib
16
{
17
	/**
18
	 * @param string      $string
19
	 * @param bool        $hex
20
	 * @param bool        $spaces
21
	 * @param string|bool $htmlencoding
22
	 *
23
	 * @return string
24
	 */
25
	public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') {
26
		$returnstring = '';
27
		for ($i = 0; $i < strlen($string); $i++) {
28
			if ($hex) {
29
				$returnstring .= str_pad(dechex(ord($string[$i])), 2, '0', STR_PAD_LEFT);
30
			} else {
31
				$returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string[$i]) ? $string[$i] : '¤');
32
			}
33
			if ($spaces) {
34
				$returnstring .= ' ';
35
			}
36
		}
37
		if (!empty($htmlencoding)) {
38
			if ($htmlencoding === true) {
39
				$htmlencoding = 'UTF-8'; // prior to getID3 v1.9.0 the function's 4th parameter was boolean
40
			}
41
			$returnstring = htmlentities($returnstring, ENT_QUOTES, $htmlencoding);
42
		}
43
		return $returnstring;
44
	}
45
46
	/**
47
	 * Truncates a floating-point number at the decimal point.
48
	 *
49
	 * @param float $floatnumber
50
	 *
51
	 * @return float|int returns int (if possible, otherwise float)
52
	 */
53 View Code Duplication
	public static function trunc($floatnumber) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
54
		if ($floatnumber >= 1) {
55
			$truncatednumber = floor($floatnumber);
56
		} elseif ($floatnumber <= -1) {
57
			$truncatednumber = ceil($floatnumber);
58
		} else {
59
			$truncatednumber = 0;
60
		}
61
		if (self::intValueSupported($truncatednumber)) {
62
			$truncatednumber = (int) $truncatednumber;
63
		}
64
		return $truncatednumber;
65
	}
66
67
	/**
68
	 * @param int|null $variable
69
	 * @param int      $increment
70
	 *
71
	 * @return bool
72
	 */
73
	public static function safe_inc(&$variable, $increment=1) {
74
		if (isset($variable)) {
75
			$variable += $increment;
76
		} else {
77
			$variable = $increment;
78
		}
79
		return true;
80
	}
81
82
	/**
83
	 * @param int|float $floatnum
84
	 *
85
	 * @return int|float
86
	 */
87
	public static function CastAsInt($floatnum) {
88
		// convert to float if not already
89
		$floatnum = (float) $floatnum;
90
91
		// convert a float to type int, only if possible
92
		if (self::trunc($floatnum) == $floatnum) {
93
			// it's not floating point
94
			if (self::intValueSupported($floatnum)) {
95
				// it's within int range
96
				$floatnum = (int) $floatnum;
97
			}
98
		}
99
		return $floatnum;
100
	}
101
102
	/**
103
	 * @param int $num
104
	 *
105
	 * @return bool
106
	 */
107
	public static function intValueSupported($num) {
108
		// check if integers are 64-bit
109
		static $hasINT64 = null;
110
		if ($hasINT64 === null) { // 10x faster than is_null()
111
			$hasINT64 = is_int(pow(2, 31)); // 32-bit int are limited to (2^31)-1
112
			if (!$hasINT64 && !defined('PHP_INT_MIN')) {
113
				define('PHP_INT_MIN', ~PHP_INT_MAX);
114
			}
115
		}
116
		// if integers are 64-bit - no other check required
117
		if ($hasINT64 || (($num <= PHP_INT_MAX) && ($num >= PHP_INT_MIN))) {
118
			return true;
119
		}
120
		return false;
121
	}
122
123
	/**
124
	 * @param string $fraction
125
	 *
126
	 * @return float
127
	 */
128
	public static function DecimalizeFraction($fraction) {
129
		list($numerator, $denominator) = explode('/', $fraction);
130
		return $numerator / ($denominator ? $denominator : 1);
131
	}
132
133
	/**
134
	 * @param string $binarynumerator
135
	 *
136
	 * @return float
137
	 */
138
	public static function DecimalBinary2Float($binarynumerator) {
139
		$numerator   = self::Bin2Dec($binarynumerator);
140
		$denominator = self::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator)));
141
		return ($numerator / $denominator);
142
	}
143
144
	/**
145
	 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
146
	 *
147
	 * @param string $binarypointnumber
148
	 * @param int    $maxbits
149
	 *
150
	 * @return array
151
	 */
152 View Code Duplication
	public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
153
		if (strpos($binarypointnumber, '.') === false) {
154
			$binarypointnumber = '0.'.$binarypointnumber;
155
		} elseif ($binarypointnumber[0] == '.') {
156
			$binarypointnumber = '0'.$binarypointnumber;
157
		}
158
		$exponent = 0;
159
		while (($binarypointnumber[0] != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
160
			if (substr($binarypointnumber, 1, 1) == '.') {
161
				$exponent--;
162
				$binarypointnumber = substr($binarypointnumber, 2, 1).'.'.substr($binarypointnumber, 3);
163
			} else {
164
				$pointpos = strpos($binarypointnumber, '.');
165
				$exponent += ($pointpos - 1);
166
				$binarypointnumber = str_replace('.', '', $binarypointnumber);
167
				$binarypointnumber = $binarypointnumber[0].'.'.substr($binarypointnumber, 1);
168
			}
169
		}
170
		$binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT);
171
		return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent);
172
	}
173
174
	/**
175
	 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
176
	 *
177
	 * @param float $floatvalue
178
	 *
179
	 * @return string
180
	 */
181
	public static function Float2BinaryDecimal($floatvalue) {
182
		$maxbits = 128; // to how many bits of precision should the calculations be taken?
183
		$intpart   = self::trunc($floatvalue);
184
		$floatpart = abs($floatvalue - $intpart);
185
		$pointbitstring = '';
186 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...
187
			$floatpart *= 2;
188
			$pointbitstring .= (string) self::trunc($floatpart);
189
			$floatpart -= self::trunc($floatpart);
190
		}
191
		$binarypointnumber = decbin($intpart).'.'.$pointbitstring;
192
		return $binarypointnumber;
193
	}
194
195
	/**
196
	 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
197
	 *
198
	 * @param float $floatvalue
199
	 * @param int $bits
200
	 *
201
	 * @return string|false
202
	 */
203
	public static function Float2String($floatvalue, $bits) {
204
		$exponentbits = 0;
0 ignored issues
show
Unused Code introduced by
$exponentbits 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...
205
		$fractionbits = 0;
0 ignored issues
show
Unused Code introduced by
$fractionbits 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...
206 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...
207
			case 32:
208
				$exponentbits = 8;
209
				$fractionbits = 23;
210
				break;
211
212
			case 64:
213
				$exponentbits = 11;
214
				$fractionbits = 52;
215
				break;
216
217
			default:
218
				return false;
219
		}
220
		if ($floatvalue >= 0) {
221
			$signbit = '0';
222
		} else {
223
			$signbit = '1';
224
		}
225
		$normalizedbinary  = self::NormalizeBinaryPoint(self::Float2BinaryDecimal($floatvalue), $fractionbits);
226
		$biasedexponent    = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent
227
		$exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits, '0', STR_PAD_LEFT);
228
		$fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2), $fractionbits, '0', STR_PAD_RIGHT);
229
230
		return self::BigEndian2String(self::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
231
	}
232
233
	/**
234
	 * @param string $byteword
235
	 *
236
	 * @return float|false
237
	 */
238
	public static function LittleEndian2Float($byteword) {
239
		return self::BigEndian2Float(strrev($byteword));
240
	}
241
242
	/**
243
	 * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
244
	 *
245
	 * @link http://www.psc.edu/general/software/packages/ieee/ieee.html
246
	 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
247
	 *
248
	 * @param string $byteword
249
	 *
250
	 * @return float|false
251
	 */
252
	public static function BigEndian2Float($byteword) {
253
		$bitword = self::BigEndian2Bin($byteword);
254
		if (!$bitword) {
255
			return 0;
256
		}
257
		$signbit = $bitword[0];
258
		$floatvalue = 0;
259
		$exponentbits = 0;
0 ignored issues
show
Unused Code introduced by
$exponentbits 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...
260
		$fractionbits = 0;
0 ignored issues
show
Unused Code introduced by
$fractionbits 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...
261
262
		switch (strlen($byteword) * 8) {
263
			case 32:
264
				$exponentbits = 8;
265
				$fractionbits = 23;
266
				break;
267
268
			case 64:
269
				$exponentbits = 11;
270
				$fractionbits = 52;
271
				break;
272
273
			case 80:
274
				// 80-bit Apple SANE format
275
				// http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
276
				$exponentstring = substr($bitword, 1, 15);
277
				$isnormalized = intval($bitword[16]);
278
				$fractionstring = substr($bitword, 17, 63);
279
				$exponent = pow(2, self::Bin2Dec($exponentstring) - 16383);
280
				$fraction = $isnormalized + self::DecimalBinary2Float($fractionstring);
281
				$floatvalue = $exponent * $fraction;
282
				if ($signbit == '1') {
283
					$floatvalue *= -1;
284
				}
285
				return $floatvalue;
286
287
			default:
288
				return false;
289
		}
290
		$exponentstring = substr($bitword, 1, $exponentbits);
291
		$fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
292
		$exponent = self::Bin2Dec($exponentstring);
293
		$fraction = self::Bin2Dec($fractionstring);
294
295 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...
296
			// Not a Number
297
			$floatvalue = false;
298
		} elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) {
299
			if ($signbit == '1') {
300
				$floatvalue = '-infinity';
301
			} else {
302
				$floatvalue = '+infinity';
303
			}
304
		} elseif (($exponent == 0) && ($fraction == 0)) {
305
			if ($signbit == '1') {
306
				$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...
307
			} else {
308
				$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...
309
			}
310
			$floatvalue = ($signbit ? 0 : -0);
311
		} elseif (($exponent == 0) && ($fraction != 0)) {
312
			// These are 'unnormalized' values
313
			$floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * self::DecimalBinary2Float($fractionstring);
314
			if ($signbit == '1') {
315
				$floatvalue *= -1;
316
			}
317
		} elseif ($exponent != 0) {
318
			$floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + self::DecimalBinary2Float($fractionstring));
319
			if ($signbit == '1') {
320
				$floatvalue *= -1;
321
			}
322
		}
323
		return (float) $floatvalue;
324
	}
325
326
	/**
327
	 * @param string $byteword
328
	 * @param bool   $synchsafe
329
	 * @param bool   $signed
330
	 *
331
	 * @return int|float|false
332
	 * @throws Exception
333
	 */
334
	public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
335
		$intvalue = 0;
336
		$bytewordlen = strlen($byteword);
337
		if ($bytewordlen == 0) {
338
			return false;
339
		}
340 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...
341
			if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
342
				//$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7); // faster, but runs into problems past 2^31 on 32-bit systems
343
				$intvalue += (ord($byteword[$i]) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7);
344
			} else {
345
				$intvalue += ord($byteword[$i]) * pow(256, ($bytewordlen - 1 - $i));
346
			}
347
		}
348
		if ($signed && !$synchsafe) {
349
			// synchsafe ints are not allowed to be signed
350
			if ($bytewordlen <= PHP_INT_SIZE) {
351
				$signMaskBit = 0x80 << (8 * ($bytewordlen - 1));
352
				if ($intvalue & $signMaskBit) {
353
					$intvalue = 0 - ($intvalue & ($signMaskBit - 1));
354
				}
355
			} else {
356
				throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits ('.strlen($byteword).') in self::BigEndian2Int()');
357
			}
358
		}
359
		return self::CastAsInt($intvalue);
360
	}
361
362
	/**
363
	 * @param string $byteword
364
	 * @param bool   $signed
365
	 *
366
	 * @return int|float|false
367
	 */
368
	public static function LittleEndian2Int($byteword, $signed=false) {
369
		return self::BigEndian2Int(strrev($byteword), false, $signed);
370
	}
371
372
	/**
373
	 * @param string $byteword
374
	 *
375
	 * @return string
376
	 */
377
	public static function LittleEndian2Bin($byteword) {
378
		return self::BigEndian2Bin(strrev($byteword));
379
	}
380
381
	/**
382
	 * @param string $byteword
383
	 *
384
	 * @return string
385
	 */
386 View Code Duplication
	public static function BigEndian2Bin($byteword) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
387
		$binvalue = '';
388
		$bytewordlen = strlen($byteword);
389
		for ($i = 0; $i < $bytewordlen; $i++) {
390
			$binvalue .= str_pad(decbin(ord($byteword[$i])), 8, '0', STR_PAD_LEFT);
391
		}
392
		return $binvalue;
393
	}
394
395
	/**
396
	 * @param int  $number
397
	 * @param int  $minbytes
398
	 * @param bool $synchsafe
399
	 * @param bool $signed
400
	 *
401
	 * @return string
402
	 * @throws Exception
403
	 */
404
	public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
405
		if ($number < 0) {
406
			throw new Exception('ERROR: self::BigEndian2String() does not support negative numbers');
407
		}
408
		$maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF);
409
		$intstring = '';
410
		if ($signed) {
411
			if ($minbytes > PHP_INT_SIZE) {
412
				throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits in self::BigEndian2String()');
413
			}
414
			$number = $number & (0x80 << (8 * ($minbytes - 1)));
415
		}
416 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...
417
			$quotient = ($number / ($maskbyte + 1));
418
			$intstring = chr(ceil(($quotient - floor($quotient)) * $maskbyte)).$intstring;
419
			$number = floor($quotient);
420
		}
421
		return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT);
422
	}
423
424
	/**
425
	 * @param int $number
426
	 *
427
	 * @return string
428
	 */
429 View Code Duplication
	public static function Dec2Bin($number) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
430
		while ($number >= 256) {
431
			$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...
432
			$number = floor($number / 256);
433
		}
434
		$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...
435
		$binstring = '';
436
		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...
437
			$binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, '0', STR_PAD_LEFT)).$binstring;
438
		}
439
		return $binstring;
440
	}
441
442
	/**
443
	 * @param string $binstring
444
	 * @param bool   $signed
445
	 *
446
	 * @return int|float
447
	 */
448
	public static function Bin2Dec($binstring, $signed=false) {
449
		$signmult = 1;
450
		if ($signed) {
451
			if ($binstring[0] == '1') {
452
				$signmult = -1;
453
			}
454
			$binstring = substr($binstring, 1);
455
		}
456
		$decvalue = 0;
457 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...
458
			$decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
459
		}
460
		return self::CastAsInt($decvalue * $signmult);
461
	}
462
463
	/**
464
	 * @param string $binstring
465
	 *
466
	 * @return string
467
	 */
468 View Code Duplication
	public static function Bin2String($binstring) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
469
		// return 'hi' for input of '0110100001101001'
470
		$string = '';
471
		$binstringreversed = strrev($binstring);
472
		for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
473
			$string = chr(self::Bin2Dec(strrev(substr($binstringreversed, $i, 8)))).$string;
474
		}
475
		return $string;
476
	}
477
478
	/**
479
	 * @param int  $number
480
	 * @param int  $minbytes
481
	 * @param bool $synchsafe
482
	 *
483
	 * @return string
484
	 */
485 View Code Duplication
	public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
486
		$intstring = '';
487
		while ($number > 0) {
488
			if ($synchsafe) {
489
				$intstring = $intstring.chr($number & 127);
490
				$number >>= 7;
491
			} else {
492
				$intstring = $intstring.chr($number & 255);
493
				$number >>= 8;
494
			}
495
		}
496
		return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
497
	}
498
499
	/**
500
	 * @param mixed $array1
501
	 * @param mixed $array2
502
	 *
503
	 * @return array|false
504
	 */
505
	public static function array_merge_clobber($array1, $array2) {
506
		// written by kcØhireability*com
507
		// taken from http://www.php.net/manual/en/function.array-merge-recursive.php
508
		if (!is_array($array1) || !is_array($array2)) {
509
			return false;
510
		}
511
		$newarray = $array1;
512
		foreach ($array2 as $key => $val) {
513
			if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
514
				$newarray[$key] = self::array_merge_clobber($newarray[$key], $val);
515
			} else {
516
				$newarray[$key] = $val;
517
			}
518
		}
519
		return $newarray;
520
	}
521
522
	/**
523
	 * @param mixed $array1
524
	 * @param mixed $array2
525
	 *
526
	 * @return array|false
527
	 */
528
	public static function array_merge_noclobber($array1, $array2) {
529
		if (!is_array($array1) || !is_array($array2)) {
530
			return false;
531
		}
532
		$newarray = $array1;
533
		foreach ($array2 as $key => $val) {
534
			if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
535
				$newarray[$key] = self::array_merge_noclobber($newarray[$key], $val);
536
			} elseif (!isset($newarray[$key])) {
537
				$newarray[$key] = $val;
538
			}
539
		}
540
		return $newarray;
541
	}
542
543
	/**
544
	 * @param mixed $array1
545
	 * @param mixed $array2
546
	 *
547
	 * @return array|false|null
548
	 */
549
	public static function flipped_array_merge_noclobber($array1, $array2) {
550
		if (!is_array($array1) || !is_array($array2)) {
551
			return false;
552
		}
553
		# naturally, this only works non-recursively
554
		$newarray = array_flip($array1);
555
		foreach (array_flip($array2) as $key => $val) {
556
			if (!isset($newarray[$key])) {
557
				$newarray[$key] = count($newarray);
558
			}
559
		}
560
		return array_flip($newarray);
561
	}
562
563
	/**
564
	 * @param array $theArray
565
	 *
566
	 * @return bool
567
	 */
568
	public static function ksort_recursive(&$theArray) {
569
		ksort($theArray);
570
		foreach ($theArray as $key => $value) {
571
			if (is_array($value)) {
572
				self::ksort_recursive($theArray[$key]);
573
			}
574
		}
575
		return true;
576
	}
577
578
	/**
579
	 * @param string $filename
580
	 * @param int    $numextensions
581
	 *
582
	 * @return string
583
	 */
584 View Code Duplication
	public static function fileextension($filename, $numextensions=1) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
585
		if (strstr($filename, '.')) {
586
			$reversedfilename = strrev($filename);
587
			$offset = 0;
588
			for ($i = 0; $i < $numextensions; $i++) {
589
				$offset = strpos($reversedfilename, '.', $offset + 1);
590
				if ($offset === false) {
591
					return '';
592
				}
593
			}
594
			return strrev(substr($reversedfilename, 0, $offset));
595
		}
596
		return '';
597
	}
598
599
	/**
600
	 * @param int $seconds
601
	 *
602
	 * @return string
603
	 */
604
	public static function PlaytimeString($seconds) {
605
		$sign = (($seconds < 0) ? '-' : '');
606
		$seconds = round(abs($seconds));
607
		$H = (int) floor( $seconds                            / 3600);
608
		$M = (int) floor(($seconds - (3600 * $H)            ) /   60);
609
		$S = (int) round( $seconds - (3600 * $H) - (60 * $M)        );
610
		return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT);
611
	}
612
613
	/**
614
	 * @param int $macdate
615
	 *
616
	 * @return int|float
617
	 */
618
	public static function DateMac2Unix($macdate) {
619
		// Macintosh timestamp: seconds since 00:00h January 1, 1904
620
		// UNIX timestamp:      seconds since 00:00h January 1, 1970
621
		return self::CastAsInt($macdate - 2082844800);
622
	}
623
624
	/**
625
	 * @param string $rawdata
626
	 *
627
	 * @return float
628
	 */
629
	public static function FixedPoint8_8($rawdata) {
630
		return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
631
	}
632
633
	/**
634
	 * @param string $rawdata
635
	 *
636
	 * @return float
637
	 */
638
	public static function FixedPoint16_16($rawdata) {
639
		return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
640
	}
641
642
	/**
643
	 * @param string $rawdata
644
	 *
645
	 * @return float
646
	 */
647
	public static function FixedPoint2_30($rawdata) {
648
		$binarystring = self::BigEndian2Bin($rawdata);
649
		return self::Bin2Dec(substr($binarystring, 0, 2)) + (float) (self::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
650
	}
651
652
653
	/**
654
	 * @param string $ArrayPath
655
	 * @param string $Separator
656
	 * @param mixed $Value
657
	 *
658
	 * @return array
659
	 */
660
	public static function CreateDeepArray($ArrayPath, $Separator, $Value) {
661
		// assigns $Value to a nested array path:
662
		//   $foo = self::CreateDeepArray('/path/to/my', '/', 'file.txt')
663
		// is the same as:
664
		//   $foo = array('path'=>array('to'=>'array('my'=>array('file.txt'))));
665
		// or
666
		//   $foo['path']['to']['my'] = 'file.txt';
667
		$ArrayPath = ltrim($ArrayPath, $Separator);
668 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...
669
			$ReturnedArray[substr($ArrayPath, 0, $pos)] = self::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...
670
		} else {
671
			$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...
672
		}
673
		return $ReturnedArray;
674
	}
675
676
	/**
677
	 * @param array $arraydata
678
	 * @param bool  $returnkey
679
	 *
680
	 * @return int|false
681
	 */
682 View Code Duplication
	public static function array_max($arraydata, $returnkey=false) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
683
		$maxvalue = false;
684
		$maxkey = false;
685
		foreach ($arraydata as $key => $value) {
686
			if (!is_array($value)) {
687
				if ($value > $maxvalue) {
688
					$maxvalue = $value;
689
					$maxkey = $key;
690
				}
691
			}
692
		}
693
		return ($returnkey ? $maxkey : $maxvalue);
694
	}
695
696
	/**
697
	 * @param array $arraydata
698
	 * @param bool  $returnkey
699
	 *
700
	 * @return int|false
701
	 */
702 View Code Duplication
	public static function array_min($arraydata, $returnkey=false) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
703
		$minvalue = false;
704
		$minkey = false;
705
		foreach ($arraydata as $key => $value) {
706
			if (!is_array($value)) {
707
				if ($value > $minvalue) {
708
					$minvalue = $value;
709
					$minkey = $key;
710
				}
711
			}
712
		}
713
		return ($returnkey ? $minkey : $minvalue);
714
	}
715
716
	/**
717
	 * @param string $XMLstring
718
	 *
719
	 * @return array|false
720
	 */
721
	public static function XML2array($XMLstring) {
722
		if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) {
723
			// http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
724
			// https://core.trac.wordpress.org/changeset/29378
725
			$loader = libxml_disable_entity_loader(true);
726
			$XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', LIBXML_NOENT);
727
			$return = self::SimpleXMLelement2array($XMLobject);
728
			libxml_disable_entity_loader($loader);
729
			return $return;
730
		}
731
		return false;
732
	}
733
734
	/**
735
	* @param SimpleXMLElement|array|mixed $XMLobject
736
	*
737
	* @return mixed
738
	*/
739
	public static function SimpleXMLelement2array($XMLobject) {
740
		if (!is_object($XMLobject) && !is_array($XMLobject)) {
741
			return $XMLobject;
742
		}
743
		$XMLarray = $XMLobject instanceof SimpleXMLElement ? get_object_vars($XMLobject) : $XMLobject;
744
		foreach ($XMLarray as $key => $value) {
745
			$XMLarray[$key] = self::SimpleXMLelement2array($value);
746
		}
747
		return $XMLarray;
748
	}
749
750
	/**
751
	 * Returns checksum for a file from starting position to absolute end position.
752
	 *
753
	 * @param string $file
754
	 * @param int    $offset
755
	 * @param int    $end
756
	 * @param string $algorithm
757
	 *
758
	 * @return string|false
759
	 * @throws getid3_exception
760
	 */
761
	public static function hash_data($file, $offset, $end, $algorithm) {
762
		if (!self::intValueSupported($end)) {
763
			return false;
764
		}
765
		if (!in_array($algorithm, array('md5', 'sha1'))) {
766
			throw new getid3_exception('Invalid algorithm ('.$algorithm.') in self::hash_data()');
767
		}
768
769
		$size = $end - $offset;
770
771
		$fp = fopen($file, 'rb');
772
		fseek($fp, $offset);
773
		$ctx = hash_init($algorithm);
774
		while ($size > 0) {
775
			$buffer = fread($fp, min($size, getID3::FREAD_BUFFER_SIZE));
776
			hash_update($ctx, $buffer);
777
			$size -= getID3::FREAD_BUFFER_SIZE;
778
		}
779
		$hash = hash_final($ctx);
780
		fclose($fp);
781
782
		return $hash;
783
	}
784
785
	/**
786
	 * @param string $filename_source
787
	 * @param string $filename_dest
788
	 * @param int    $offset
789
	 * @param int    $length
790
	 *
791
	 * @return bool
792
	 * @throws Exception
793
	 *
794
	 * @deprecated Unused, may be removed in future versions of getID3
795
	 */
796
	public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) {
797
		if (!self::intValueSupported($offset + $length)) {
798
			throw new Exception('cannot copy file portion, it extends beyond the '.round(PHP_INT_MAX / 1073741824).'GB limit');
799
		}
800
		if (is_readable($filename_source) && is_file($filename_source) && ($fp_src = fopen($filename_source, 'rb'))) {
801
			if (($fp_dest = fopen($filename_dest, 'wb'))) {
802
				if (fseek($fp_src, $offset) == 0) {
803
					$byteslefttowrite = $length;
804
					while (($byteslefttowrite > 0) && ($buffer = fread($fp_src, min($byteslefttowrite, getID3::FREAD_BUFFER_SIZE)))) {
805
						$byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite);
806
						$byteslefttowrite -= $byteswritten;
807
					}
808
					fclose($fp_dest);
809
					return true;
810
				} else {
811
					fclose($fp_src);
812
					throw new Exception('failed to seek to offset '.$offset.' in '.$filename_source);
813
				}
814
			} else {
815
				throw new Exception('failed to create file for writing '.$filename_dest);
816
			}
817
		} else {
818
			throw new Exception('failed to open file for reading '.$filename_source);
819
		}
820
	}
821
822
	/**
823
	 * @param int $charval
824
	 *
825
	 * @return string
826
	 */
827
	public static function iconv_fallback_int_utf8($charval) {
828
		if ($charval < 128) {
829
			// 0bbbbbbb
830
			$newcharstring = chr($charval);
831
		} elseif ($charval < 2048) {
832
			// 110bbbbb 10bbbbbb
833
			$newcharstring  = chr(($charval >>   6) | 0xC0);
834
			$newcharstring .= chr(($charval & 0x3F) | 0x80);
835
		} elseif ($charval < 65536) {
836
			// 1110bbbb 10bbbbbb 10bbbbbb
837
			$newcharstring  = chr(($charval >>  12) | 0xE0);
838
			$newcharstring .= chr(($charval >>   6) | 0xC0);
839
			$newcharstring .= chr(($charval & 0x3F) | 0x80);
840
		} else {
841
			// 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
842
			$newcharstring  = chr(($charval >>  18) | 0xF0);
843
			$newcharstring .= chr(($charval >>  12) | 0xC0);
844
			$newcharstring .= chr(($charval >>   6) | 0xC0);
845
			$newcharstring .= chr(($charval & 0x3F) | 0x80);
846
		}
847
		return $newcharstring;
848
	}
849
850
	/**
851
	 * ISO-8859-1 => UTF-8
852
	 *
853
	 * @param string $string
854
	 * @param bool   $bom
855
	 *
856
	 * @return string
857
	 */
858
	public static function iconv_fallback_iso88591_utf8($string, $bom=false) {
859
		if (function_exists('utf8_encode')) {
860
			return utf8_encode($string);
861
		}
862
		// utf8_encode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
863
		$newcharstring = '';
864
		if ($bom) {
865
			$newcharstring .= "\xEF\xBB\xBF";
866
		}
867
		for ($i = 0; $i < strlen($string); $i++) {
868
			$charval = ord($string[$i]);
869
			$newcharstring .= self::iconv_fallback_int_utf8($charval);
870
		}
871
		return $newcharstring;
872
	}
873
874
	/**
875
	 * ISO-8859-1 => UTF-16BE
876
	 *
877
	 * @param string $string
878
	 * @param bool   $bom
879
	 *
880
	 * @return string
881
	 */
882 View Code Duplication
	public static function iconv_fallback_iso88591_utf16be($string, $bom=false) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
883
		$newcharstring = '';
884
		if ($bom) {
885
			$newcharstring .= "\xFE\xFF";
886
		}
887
		for ($i = 0; $i < strlen($string); $i++) {
888
			$newcharstring .= "\x00".$string[$i];
889
		}
890
		return $newcharstring;
891
	}
892
893
	/**
894
	 * ISO-8859-1 => UTF-16LE
895
	 *
896
	 * @param string $string
897
	 * @param bool   $bom
898
	 *
899
	 * @return string
900
	 */
901 View Code Duplication
	public static function iconv_fallback_iso88591_utf16le($string, $bom=false) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
902
		$newcharstring = '';
903
		if ($bom) {
904
			$newcharstring .= "\xFF\xFE";
905
		}
906
		for ($i = 0; $i < strlen($string); $i++) {
907
			$newcharstring .= $string[$i]."\x00";
908
		}
909
		return $newcharstring;
910
	}
911
912
	/**
913
	 * ISO-8859-1 => UTF-16LE (BOM)
914
	 *
915
	 * @param string $string
916
	 *
917
	 * @return string
918
	 */
919
	public static function iconv_fallback_iso88591_utf16($string) {
920
		return self::iconv_fallback_iso88591_utf16le($string, true);
921
	}
922
923
	/**
924
	 * UTF-8 => ISO-8859-1
925
	 *
926
	 * @param string $string
927
	 *
928
	 * @return string
929
	 */
930
	public static function iconv_fallback_utf8_iso88591($string) {
931
		if (function_exists('utf8_decode')) {
932
			return utf8_decode($string);
933
		}
934
		// utf8_decode() unavailable, use getID3()'s iconv_fallback() conversions (possibly PHP is compiled without XML support)
935
		$newcharstring = '';
936
		$offset = 0;
937
		$stringlength = strlen($string);
938
		while ($offset < $stringlength) {
939
			if ((ord($string[$offset]) | 0x07) == 0xF7) {
940
				// 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
941
				$charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
942
						   ((ord($string[($offset + 1)]) & 0x3F) << 12) &
943
						   ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
944
							(ord($string[($offset + 3)]) & 0x3F);
945
				$offset += 4;
946
			} elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
947
				// 1110bbbb 10bbbbbb 10bbbbbb
948
				$charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
949
						   ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
950
							(ord($string[($offset + 2)]) & 0x3F);
951
				$offset += 3;
952
			} elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
953
				// 110bbbbb 10bbbbbb
954
				$charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
955
							(ord($string[($offset + 1)]) & 0x3F);
956
				$offset += 2;
957
			} elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
958
				// 0bbbbbbb
959
				$charval = ord($string[$offset]);
960
				$offset += 1;
961
			} else {
962
				// error? throw some kind of warning here?
963
				$charval = false;
964
				$offset += 1;
965
			}
966
			if ($charval !== false) {
967
				$newcharstring .= (($charval < 256) ? chr($charval) : '?');
968
			}
969
		}
970
		return $newcharstring;
971
	}
972
973
	/**
974
	 * UTF-8 => UTF-16BE
975
	 *
976
	 * @param string $string
977
	 * @param bool   $bom
978
	 *
979
	 * @return string
980
	 */
981 View Code Duplication
	public static function iconv_fallback_utf8_utf16be($string, $bom=false) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
982
		$newcharstring = '';
983
		if ($bom) {
984
			$newcharstring .= "\xFE\xFF";
985
		}
986
		$offset = 0;
987
		$stringlength = strlen($string);
988
		while ($offset < $stringlength) {
989
			if ((ord($string[$offset]) | 0x07) == 0xF7) {
990
				// 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
991
				$charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
992
						   ((ord($string[($offset + 1)]) & 0x3F) << 12) &
993
						   ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
994
							(ord($string[($offset + 3)]) & 0x3F);
995
				$offset += 4;
996
			} elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
997
				// 1110bbbb 10bbbbbb 10bbbbbb
998
				$charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
999
						   ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
1000
							(ord($string[($offset + 2)]) & 0x3F);
1001
				$offset += 3;
1002
			} elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
1003
				// 110bbbbb 10bbbbbb
1004
				$charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
1005
							(ord($string[($offset + 1)]) & 0x3F);
1006
				$offset += 2;
1007
			} elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
1008
				// 0bbbbbbb
1009
				$charval = ord($string[$offset]);
1010
				$offset += 1;
1011
			} else {
1012
				// error? throw some kind of warning here?
1013
				$charval = false;
1014
				$offset += 1;
1015
			}
1016
			if ($charval !== false) {
1017
				$newcharstring .= (($charval < 65536) ? self::BigEndian2String($charval, 2) : "\x00".'?');
1018
			}
1019
		}
1020
		return $newcharstring;
1021
	}
1022
1023
	/**
1024
	 * UTF-8 => UTF-16LE
1025
	 *
1026
	 * @param string $string
1027
	 * @param bool   $bom
1028
	 *
1029
	 * @return string
1030
	 */
1031 View Code Duplication
	public static function iconv_fallback_utf8_utf16le($string, $bom=false) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1032
		$newcharstring = '';
1033
		if ($bom) {
1034
			$newcharstring .= "\xFF\xFE";
1035
		}
1036
		$offset = 0;
1037
		$stringlength = strlen($string);
1038
		while ($offset < $stringlength) {
1039
			if ((ord($string[$offset]) | 0x07) == 0xF7) {
1040
				// 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
1041
				$charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
1042
						   ((ord($string[($offset + 1)]) & 0x3F) << 12) &
1043
						   ((ord($string[($offset + 2)]) & 0x3F) <<  6) &
1044
							(ord($string[($offset + 3)]) & 0x3F);
1045
				$offset += 4;
1046
			} elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
1047
				// 1110bbbb 10bbbbbb 10bbbbbb
1048
				$charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
1049
						   ((ord($string[($offset + 1)]) & 0x3F) <<  6) &
1050
							(ord($string[($offset + 2)]) & 0x3F);
1051
				$offset += 3;
1052
			} elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
1053
				// 110bbbbb 10bbbbbb
1054
				$charval = ((ord($string[($offset + 0)]) & 0x1F) <<  6) &
1055
							(ord($string[($offset + 1)]) & 0x3F);
1056
				$offset += 2;
1057
			} elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
1058
				// 0bbbbbbb
1059
				$charval = ord($string[$offset]);
1060
				$offset += 1;
1061
			} else {
1062
				// error? maybe throw some warning here?
1063
				$charval = false;
1064
				$offset += 1;
1065
			}
1066
			if ($charval !== false) {
1067
				$newcharstring .= (($charval < 65536) ? self::LittleEndian2String($charval, 2) : '?'."\x00");
1068
			}
1069
		}
1070
		return $newcharstring;
1071
	}
1072
1073
	/**
1074
	 * UTF-8 => UTF-16LE (BOM)
1075
	 *
1076
	 * @param string $string
1077
	 *
1078
	 * @return string
1079
	 */
1080
	public static function iconv_fallback_utf8_utf16($string) {
1081
		return self::iconv_fallback_utf8_utf16le($string, true);
1082
	}
1083
1084
	/**
1085
	 * UTF-16BE => UTF-8
1086
	 *
1087
	 * @param string $string
1088
	 *
1089
	 * @return string
1090
	 */
1091 View Code Duplication
	public static function iconv_fallback_utf16be_utf8($string) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1092
		if (substr($string, 0, 2) == "\xFE\xFF") {
1093
			// strip BOM
1094
			$string = substr($string, 2);
1095
		}
1096
		$newcharstring = '';
1097
		for ($i = 0; $i < strlen($string); $i += 2) {
1098
			$charval = self::BigEndian2Int(substr($string, $i, 2));
1099
			$newcharstring .= self::iconv_fallback_int_utf8($charval);
0 ignored issues
show
Bug introduced by
It seems like $charval defined by self::BigEndian2Int(substr($string, $i, 2)) on line 1098 can also be of type double or false; however, getid3_lib::iconv_fallback_int_utf8() does only seem to accept integer, maybe add an additional type check?

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

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

    return array();
}

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

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

Loading history...
1100
		}
1101
		return $newcharstring;
1102
	}
1103
1104
	/**
1105
	 * UTF-16LE => UTF-8
1106
	 *
1107
	 * @param string $string
1108
	 *
1109
	 * @return string
1110
	 */
1111 View Code Duplication
	public static function iconv_fallback_utf16le_utf8($string) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1112
		if (substr($string, 0, 2) == "\xFF\xFE") {
1113
			// strip BOM
1114
			$string = substr($string, 2);
1115
		}
1116
		$newcharstring = '';
1117
		for ($i = 0; $i < strlen($string); $i += 2) {
1118
			$charval = self::LittleEndian2Int(substr($string, $i, 2));
1119
			$newcharstring .= self::iconv_fallback_int_utf8($charval);
0 ignored issues
show
Bug introduced by
It seems like $charval defined by self::LittleEndian2Int(substr($string, $i, 2)) on line 1118 can also be of type double or false; however, getid3_lib::iconv_fallback_int_utf8() does only seem to accept integer, maybe add an additional type check?

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

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

    return array();
}

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

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

Loading history...
1120
		}
1121
		return $newcharstring;
1122
	}
1123
1124
	/**
1125
	 * UTF-16BE => ISO-8859-1
1126
	 *
1127
	 * @param string $string
1128
	 *
1129
	 * @return string
1130
	 */
1131 View Code Duplication
	public static function iconv_fallback_utf16be_iso88591($string) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1132
		if (substr($string, 0, 2) == "\xFE\xFF") {
1133
			// strip BOM
1134
			$string = substr($string, 2);
1135
		}
1136
		$newcharstring = '';
1137
		for ($i = 0; $i < strlen($string); $i += 2) {
1138
			$charval = self::BigEndian2Int(substr($string, $i, 2));
1139
			$newcharstring .= (($charval < 256) ? chr($charval) : '?');
1140
		}
1141
		return $newcharstring;
1142
	}
1143
1144
	/**
1145
	 * UTF-16LE => ISO-8859-1
1146
	 *
1147
	 * @param string $string
1148
	 *
1149
	 * @return string
1150
	 */
1151 View Code Duplication
	public static function iconv_fallback_utf16le_iso88591($string) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1152
		if (substr($string, 0, 2) == "\xFF\xFE") {
1153
			// strip BOM
1154
			$string = substr($string, 2);
1155
		}
1156
		$newcharstring = '';
1157
		for ($i = 0; $i < strlen($string); $i += 2) {
1158
			$charval = self::LittleEndian2Int(substr($string, $i, 2));
1159
			$newcharstring .= (($charval < 256) ? chr($charval) : '?');
1160
		}
1161
		return $newcharstring;
1162
	}
1163
1164
	/**
1165
	 * UTF-16 (BOM) => ISO-8859-1
1166
	 *
1167
	 * @param string $string
1168
	 *
1169
	 * @return string
1170
	 */
1171 View Code Duplication
	public static function iconv_fallback_utf16_iso88591($string) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1172
		$bom = substr($string, 0, 2);
1173
		if ($bom == "\xFE\xFF") {
1174
			return self::iconv_fallback_utf16be_iso88591(substr($string, 2));
1175
		} elseif ($bom == "\xFF\xFE") {
1176
			return self::iconv_fallback_utf16le_iso88591(substr($string, 2));
1177
		}
1178
		return $string;
1179
	}
1180
1181
	/**
1182
	 * UTF-16 (BOM) => UTF-8
1183
	 *
1184
	 * @param string $string
1185
	 *
1186
	 * @return string
1187
	 */
1188 View Code Duplication
	public static function iconv_fallback_utf16_utf8($string) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1189
		$bom = substr($string, 0, 2);
1190
		if ($bom == "\xFE\xFF") {
1191
			return self::iconv_fallback_utf16be_utf8(substr($string, 2));
1192
		} elseif ($bom == "\xFF\xFE") {
1193
			return self::iconv_fallback_utf16le_utf8(substr($string, 2));
1194
		}
1195
		return $string;
1196
	}
1197
1198
	/**
1199
	 * @param string $in_charset
1200
	 * @param string $out_charset
1201
	 * @param string $string
1202
	 *
1203
	 * @return string
1204
	 * @throws Exception
1205
	 */
1206
	public static function iconv_fallback($in_charset, $out_charset, $string) {
1207
1208
		if ($in_charset == $out_charset) {
1209
			return $string;
1210
		}
1211
1212
		// mb_convert_encoding() available
1213
		if (function_exists('mb_convert_encoding')) {
1214
			if ((strtoupper($in_charset) == 'UTF-16') && (substr($string, 0, 2) != "\xFE\xFF") && (substr($string, 0, 2) != "\xFF\xFE")) {
1215
				// if BOM missing, mb_convert_encoding will mishandle the conversion, assume UTF-16BE and prepend appropriate BOM
1216
				$string = "\xFF\xFE".$string;
1217
			}
1218
			if ((strtoupper($in_charset) == 'UTF-16') && (strtoupper($out_charset) == 'UTF-8')) {
1219
				if (($string == "\xFF\xFE") || ($string == "\xFE\xFF")) {
1220
					// if string consists of only BOM, mb_convert_encoding will return the BOM unmodified
1221
					return '';
1222
				}
1223
			}
1224 View Code Duplication
			if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) {
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...
1225
				switch ($out_charset) {
1226
					case 'ISO-8859-1':
1227
						$converted_string = rtrim($converted_string, "\x00");
1228
						break;
1229
				}
1230
				return $converted_string;
1231
			}
1232
			return $string;
1233
1234
		// iconv() available
1235
		} elseif (function_exists('iconv')) {
1236 View Code Duplication
			if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
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...
1237
				switch ($out_charset) {
1238
					case 'ISO-8859-1':
1239
						$converted_string = rtrim($converted_string, "\x00");
1240
						break;
1241
				}
1242
				return $converted_string;
1243
			}
1244
1245
			// iconv() may sometimes fail with "illegal character in input string" error message
1246
			// and return an empty string, but returning the unconverted string is more useful
1247
			return $string;
1248
		}
1249
1250
1251
		// neither mb_convert_encoding or iconv() is available
1252
		static $ConversionFunctionList = array();
1253
		if (empty($ConversionFunctionList)) {
1254
			$ConversionFunctionList['ISO-8859-1']['UTF-8']    = 'iconv_fallback_iso88591_utf8';
1255
			$ConversionFunctionList['ISO-8859-1']['UTF-16']   = 'iconv_fallback_iso88591_utf16';
1256
			$ConversionFunctionList['ISO-8859-1']['UTF-16BE'] = 'iconv_fallback_iso88591_utf16be';
1257
			$ConversionFunctionList['ISO-8859-1']['UTF-16LE'] = 'iconv_fallback_iso88591_utf16le';
1258
			$ConversionFunctionList['UTF-8']['ISO-8859-1']    = 'iconv_fallback_utf8_iso88591';
1259
			$ConversionFunctionList['UTF-8']['UTF-16']        = 'iconv_fallback_utf8_utf16';
1260
			$ConversionFunctionList['UTF-8']['UTF-16BE']      = 'iconv_fallback_utf8_utf16be';
1261
			$ConversionFunctionList['UTF-8']['UTF-16LE']      = 'iconv_fallback_utf8_utf16le';
1262
			$ConversionFunctionList['UTF-16']['ISO-8859-1']   = 'iconv_fallback_utf16_iso88591';
1263
			$ConversionFunctionList['UTF-16']['UTF-8']        = 'iconv_fallback_utf16_utf8';
1264
			$ConversionFunctionList['UTF-16LE']['ISO-8859-1'] = 'iconv_fallback_utf16le_iso88591';
1265
			$ConversionFunctionList['UTF-16LE']['UTF-8']      = 'iconv_fallback_utf16le_utf8';
1266
			$ConversionFunctionList['UTF-16BE']['ISO-8859-1'] = 'iconv_fallback_utf16be_iso88591';
1267
			$ConversionFunctionList['UTF-16BE']['UTF-8']      = 'iconv_fallback_utf16be_utf8';
1268
		}
1269
		if (isset($ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)])) {
1270
			$ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
1271
			return self::$ConversionFunction($string);
1272
		}
1273
		throw new Exception('PHP does not has mb_convert_encoding() or iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
1274
	}
1275
1276
	/**
1277
	 * @param mixed  $data
1278
	 * @param string $charset
1279
	 *
1280
	 * @return mixed
1281
	 */
1282
	public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') {
1283
		if (is_string($data)) {
1284
			return self::MultiByteCharString2HTML($data, $charset);
1285
		} elseif (is_array($data)) {
1286
			$return_data = array();
1287
			foreach ($data as $key => $value) {
1288
				$return_data[$key] = self::recursiveMultiByteCharString2HTML($value, $charset);
1289
			}
1290
			return $return_data;
1291
		}
1292
		// integer, float, objects, resources, etc
1293
		return $data;
1294
	}
1295
1296
	/**
1297
	 * @param string|int|float $string
1298
	 * @param string           $charset
1299
	 *
1300
	 * @return string
1301
	 */
1302
	public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
1303
		$string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
1304
		$HTMLstring = '';
1305
1306
		switch (strtolower($charset)) {
1307
			case '1251':
1308
			case '1252':
1309
			case '866':
1310
			case '932':
1311
			case '936':
1312
			case '950':
1313
			case 'big5':
1314
			case 'big5-hkscs':
1315
			case 'cp1251':
1316
			case 'cp1252':
1317
			case 'cp866':
1318
			case 'euc-jp':
1319
			case 'eucjp':
1320
			case 'gb2312':
1321
			case 'ibm866':
1322
			case 'iso-8859-1':
1323
			case 'iso-8859-15':
1324
			case 'iso8859-1':
1325
			case 'iso8859-15':
1326
			case 'koi8-r':
1327
			case 'koi8-ru':
1328
			case 'koi8r':
1329
			case 'shift_jis':
1330
			case 'sjis':
1331
			case 'win-1251':
1332
			case 'windows-1251':
1333
			case 'windows-1252':
1334
				$HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
1335
				break;
1336
1337
			case 'utf-8':
1338
				$strlen = strlen($string);
1339
				for ($i = 0; $i < $strlen; $i++) {
1340
					$char_ord_val = ord($string[$i]);
1341
					$charval = 0;
1342
					if ($char_ord_val < 0x80) {
1343
						$charval = $char_ord_val;
1344
					} elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F  &&  $i+3 < $strlen) {
1345
						$charval  = (($char_ord_val & 0x07) << 18);
1346
						$charval += ((ord($string[++$i]) & 0x3F) << 12);
1347
						$charval += ((ord($string[++$i]) & 0x3F) << 6);
1348
						$charval +=  (ord($string[++$i]) & 0x3F);
1349
					} elseif ((($char_ord_val & 0xE0) >> 5) == 0x07  &&  $i+2 < $strlen) {
1350
						$charval  = (($char_ord_val & 0x0F) << 12);
1351
						$charval += ((ord($string[++$i]) & 0x3F) << 6);
1352
						$charval +=  (ord($string[++$i]) & 0x3F);
1353
					} elseif ((($char_ord_val & 0xC0) >> 6) == 0x03  &&  $i+1 < $strlen) {
1354
						$charval  = (($char_ord_val & 0x1F) << 6);
1355
						$charval += (ord($string[++$i]) & 0x3F);
1356
					}
1357
					if (($charval >= 32) && ($charval <= 127)) {
1358
						$HTMLstring .= htmlentities(chr($charval));
1359
					} else {
1360
						$HTMLstring .= '&#'.$charval.';';
1361
					}
1362
				}
1363
				break;
1364
1365 View Code Duplication
			case 'utf-16le':
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...
1366
				for ($i = 0; $i < strlen($string); $i += 2) {
1367
					$charval = self::LittleEndian2Int(substr($string, $i, 2));
1368
					if (($charval >= 32) && ($charval <= 127)) {
1369
						$HTMLstring .= chr($charval);
1370
					} else {
1371
						$HTMLstring .= '&#'.$charval.';';
1372
					}
1373
				}
1374
				break;
1375
1376 View Code Duplication
			case 'utf-16be':
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...
1377
				for ($i = 0; $i < strlen($string); $i += 2) {
1378
					$charval = self::BigEndian2Int(substr($string, $i, 2));
1379
					if (($charval >= 32) && ($charval <= 127)) {
1380
						$HTMLstring .= chr($charval);
1381
					} else {
1382
						$HTMLstring .= '&#'.$charval.';';
1383
					}
1384
				}
1385
				break;
1386
1387
			default:
1388
				$HTMLstring = 'ERROR: Character set "'.$charset.'" not supported in MultiByteCharString2HTML()';
1389
				break;
1390
		}
1391
		return $HTMLstring;
1392
	}
1393
1394
	/**
1395
	 * @param int $namecode
1396
	 *
1397
	 * @return string
1398
	 */
1399 View Code Duplication
	public static function RGADnameLookup($namecode) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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

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

Loading history...
1400
		static $RGADname = array();
1401
		if (empty($RGADname)) {
1402
			$RGADname[0] = 'not set';
1403
			$RGADname[1] = 'Track Gain Adjustment';
1404
			$RGADname[2] = 'Album Gain Adjustment';
1405
		}
1406
1407
		return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : '');
1408
	}
1409
1410
	/**
1411
	 * @param int $originatorcode
1412
	 *
1413
	 * @return string
1414
	 */
1415
	public static function RGADoriginatorLookup($originatorcode) {
1416
		static $RGADoriginator = array();
1417
		if (empty($RGADoriginator)) {
1418
			$RGADoriginator[0] = 'unspecified';
1419
			$RGADoriginator[1] = 'pre-set by artist/producer/mastering engineer';
1420
			$RGADoriginator[2] = 'set by user';
1421
			$RGADoriginator[3] = 'determined automatically';
1422
		}
1423
1424
		return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : '');
1425
	}
1426
1427
	/**
1428
	 * @param int $rawadjustment
1429
	 * @param int $signbit
1430
	 *
1431
	 * @return float
1432
	 */
1433
	public static function RGADadjustmentLookup($rawadjustment, $signbit) {
1434
		$adjustment = (float) $rawadjustment / 10;
1435
		if ($signbit == 1) {
1436
			$adjustment *= -1;
1437
		}
1438
		return $adjustment;
1439
	}
1440
1441
	/**
1442
	 * @param int $namecode
1443
	 * @param int $originatorcode
1444
	 * @param int $replaygain
1445
	 *
1446
	 * @return string
1447
	 */
1448
	public static function RGADgainString($namecode, $originatorcode, $replaygain) {
1449
		if ($replaygain < 0) {
1450
			$signbit = '1';
1451
		} else {
1452
			$signbit = '0';
1453
		}
1454
		$storedreplaygain = intval(round($replaygain * 10));
1455
		$gainstring  = str_pad(decbin($namecode), 3, '0', STR_PAD_LEFT);
1456
		$gainstring .= str_pad(decbin($originatorcode), 3, '0', STR_PAD_LEFT);
1457
		$gainstring .= $signbit;
1458
		$gainstring .= str_pad(decbin($storedreplaygain), 9, '0', STR_PAD_LEFT);
1459
1460
		return $gainstring;
1461
	}
1462
1463
	/**
1464
	 * @param float $amplitude
1465
	 *
1466
	 * @return float
1467
	 */
1468
	public static function RGADamplitude2dB($amplitude) {
1469
		return 20 * log10($amplitude);
1470
	}
1471
1472
	/**
1473
	 * @param string $imgData
1474
	 * @param array  $imageinfo
1475
	 *
1476
	 * @return array|false
1477
	 */
1478
	public static function GetDataImageSize($imgData, &$imageinfo=array()) {
1479
		if (PHP_VERSION_ID >= 50400) {
1480
			$GetDataImageSize = @getimagesizefromstring($imgData, $imageinfo);
1481 View Code Duplication
			if ($GetDataImageSize === false || !isset($GetDataImageSize[0], $GetDataImageSize[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...
1482
				return false;
1483
			}
1484
			$GetDataImageSize['height'] = $GetDataImageSize[0];
1485
			$GetDataImageSize['width'] = $GetDataImageSize[1];
1486
			return $GetDataImageSize;
1487
		}
1488
		static $tempdir = '';
1489
		if (empty($tempdir)) {
1490
			if (function_exists('sys_get_temp_dir')) {
1491
				$tempdir = sys_get_temp_dir(); // https://github.com/JamesHeinrich/getID3/issues/52
1492
			}
1493
1494
			// yes this is ugly, feel free to suggest a better way
1495
			if (include_once(dirname(__FILE__).'/getid3.php')) {
1496
				$getid3_temp = new getID3();
1497
				if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
1498
					$tempdir = $getid3_temp_tempdir;
1499
				}
1500
				unset($getid3_temp, $getid3_temp_tempdir);
1501
			}
1502
		}
1503
		$GetDataImageSize = false;
1504
		if ($tempfilename = tempnam($tempdir, 'gI3')) {
1505
			if (is_writable($tempfilename) && is_file($tempfilename) && ($tmp = fopen($tempfilename, 'wb'))) {
1506
				fwrite($tmp, $imgData);
1507
				fclose($tmp);
1508
				$GetDataImageSize = @getimagesize($tempfilename, $imageinfo);
1509 View Code Duplication
				if (($GetDataImageSize === false) || !isset($GetDataImageSize[0]) || !isset($GetDataImageSize[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...
1510
					return false;
1511
				}
1512
				$GetDataImageSize['height'] = $GetDataImageSize[0];
1513
				$GetDataImageSize['width']  = $GetDataImageSize[1];
1514
			}
1515
			unlink($tempfilename);
1516
		}
1517
		return $GetDataImageSize;
1518
	}
1519
1520
	/**
1521
	 * @param string $mime_type
1522
	 *
1523
	 * @return string
1524
	 */
1525
	public static function ImageExtFromMime($mime_type) {
1526
		// temporary way, works OK for now, but should be reworked in the future
1527
		return str_replace(array('image/', 'x-', 'jpeg'), array('', '', 'jpg'), $mime_type);
1528
	}
1529
1530
	/**
1531
	 * @param array $ThisFileInfo
1532
	 *
1533
	 * @return bool
1534
	 */
1535
	public static function CopyTagsToComments(&$ThisFileInfo) {
1536
1537
		// Copy all entries from ['tags'] into common ['comments']
1538
		if (!empty($ThisFileInfo['tags'])) {
1539
			foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) {
1540
				foreach ($tagarray as $tagname => $tagdata) {
1541
					foreach ($tagdata as $key => $value) {
1542
						if (!empty($value)) {
1543
							if (empty($ThisFileInfo['comments'][$tagname])) {
1544
1545
								// fall through and append value
1546
1547
							} elseif ($tagtype == 'id3v1') {
1548
1549
								$newvaluelength = strlen(trim($value));
1550
								foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
1551
									$oldvaluelength = strlen(trim($existingvalue));
1552
									if (($newvaluelength <= $oldvaluelength) && (substr($existingvalue, 0, $newvaluelength) == trim($value))) {
1553
										// new value is identical but shorter-than (or equal-length to) one already in comments - skip
1554
										break 2;
1555
									}
1556
								}
1557
1558
							} elseif (!is_array($value)) {
1559
1560
								$newvaluelength = strlen(trim($value));
1561
								foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
1562
									$oldvaluelength = strlen(trim($existingvalue));
1563
									if ((strlen($existingvalue) > 10) && ($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) {
1564
										$ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
1565
										//break 2;
1566
										break;
1567
									}
1568
								}
1569
1570
							}
1571
							if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
1572
								$value = (is_string($value) ? trim($value) : $value);
1573
								if (!is_int($key) && !ctype_digit($key)) {
1574
									$ThisFileInfo['comments'][$tagname][$key] = $value;
1575
								} else {
1576
									if (!isset($ThisFileInfo['comments'][$tagname])) {
1577
										$ThisFileInfo['comments'][$tagname] = array($value);
1578
									} else {
1579
										$ThisFileInfo['comments'][$tagname][] = $value;
1580
									}
1581
								}
1582
							}
1583
						}
1584
					}
1585
				}
1586
			}
1587
1588
			// attempt to standardize spelling of returned keys
1589
			$StandardizeFieldNames = array(
1590
				'tracknumber' => 'track_number',
1591
				'track'       => 'track_number',
1592
			);
1593
			foreach ($StandardizeFieldNames as $badkey => $goodkey) {
1594
				if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) {
1595
					$ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey];
1596
					unset($ThisFileInfo['comments'][$badkey]);
1597
				}
1598
			}
1599
1600
			// Copy to ['comments_html']
1601
			if (!empty($ThisFileInfo['comments'])) {
1602
				foreach ($ThisFileInfo['comments'] as $field => $values) {
1603
					if ($field == 'picture') {
1604
						// pictures can take up a lot of space, and we don't need multiple copies of them
1605
						// let there be a single copy in [comments][picture], and not elsewhere
1606
						continue;
1607
					}
1608
					foreach ($values as $index => $value) {
1609
						if (is_array($value)) {
1610
							$ThisFileInfo['comments_html'][$field][$index] = $value;
1611
						} else {
1612
							$ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
1613
						}
1614
					}
1615
				}
1616
			}
1617
1618
		}
1619
		return true;
1620
	}
1621
1622
	/**
1623
	 * @param string $key
1624
	 * @param int    $begin
1625
	 * @param int    $end
1626
	 * @param string $file
1627
	 * @param string $name
1628
	 *
1629
	 * @return string
1630
	 */
1631
	public static function EmbeddedLookup($key, $begin, $end, $file, $name) {
1632
1633
		// Cached
1634
		static $cache;
1635
		if (isset($cache[$file][$name])) {
1636
			return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
1637
		}
1638
1639
		// Init
1640
		$keylength  = strlen($key);
0 ignored issues
show
Unused Code introduced by
$keylength 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...
1641
		$line_count = $end - $begin - 7;
1642
1643
		// Open php file
1644
		$fp = fopen($file, 'r');
1645
1646
		// Discard $begin lines
1647
		for ($i = 0; $i < ($begin + 3); $i++) {
1648
			fgets($fp, 1024);
1649
		}
1650
1651
		// Loop thru line
1652
		while (0 < $line_count--) {
1653
1654
			// Read line
1655
			$line = ltrim(fgets($fp, 1024), "\t ");
1656
1657
			// METHOD A: only cache the matching key - less memory but slower on next lookup of not-previously-looked-up key
1658
			//$keycheck = substr($line, 0, $keylength);
1659
			//if ($key == $keycheck)  {
1660
			//	$cache[$file][$name][$keycheck] = substr($line, $keylength + 1);
1661
			//	break;
1662
			//}
1663
1664
			// METHOD B: cache all keys in this lookup - more memory but faster on next lookup of not-previously-looked-up key
1665
			//$cache[$file][$name][substr($line, 0, $keylength)] = trim(substr($line, $keylength + 1));
1666
			$explodedLine = explode("\t", $line, 2);
1667
			$ThisKey   = (isset($explodedLine[0]) ? $explodedLine[0] : '');
1668
			$ThisValue = (isset($explodedLine[1]) ? $explodedLine[1] : '');
1669
			$cache[$file][$name][$ThisKey] = trim($ThisValue);
1670
		}
1671
1672
		// Close and return
1673
		fclose($fp);
1674
		return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
1675
	}
1676
1677
	/**
1678
	 * @param string $filename
1679
	 * @param string $sourcefile
1680
	 * @param bool   $DieOnFailure
1681
	 *
1682
	 * @return bool
1683
	 * @throws Exception
1684
	 */
1685
	public static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) {
1686
		global $GETID3_ERRORARRAY;
1687
1688
		if (file_exists($filename)) {
1689
			if (include_once($filename)) {
1690
				return true;
1691
			} else {
1692
				$diemessage = basename($sourcefile).' depends on '.$filename.', which has errors';
1693
			}
1694
		} else {
1695
			$diemessage = basename($sourcefile).' depends on '.$filename.', which is missing';
1696
		}
1697
		if ($DieOnFailure) {
1698
			throw new Exception($diemessage);
1699
		} else {
1700
			$GETID3_ERRORARRAY[] = $diemessage;
1701
		}
1702
		return false;
1703
	}
1704
1705
	/**
1706
	 * @param string $string
1707
	 *
1708
	 * @return string
1709
	 */
1710
	public static function trimNullByte($string) {
1711
		return trim($string, "\x00");
1712
	}
1713
1714
	/**
1715
	 * @param string $path
1716
	 *
1717
	 * @return float|bool
1718
	 */
1719
	public static function getFileSizeSyscall($path) {
1720
		$filesize = false;
1721
1722
		if (GETID3_OS_ISWINDOWS) {
1723
			if (class_exists('COM')) { // From PHP 5.3.15 and 5.4.5, COM and DOTNET is no longer built into the php core.you have to add COM support in php.ini:
1724
				$filesystem = new COM('Scripting.FileSystemObject');
1725
				$file = $filesystem->GetFile($path);
1726
				$filesize = $file->Size();
1727
				unset($filesystem, $file);
1728
			} else {
1729
				$commandline = 'for %I in ('.escapeshellarg($path).') do @echo %~zI';
1730
			}
1731
		} else {
1732
			$commandline = 'ls -l '.escapeshellarg($path).' | awk \'{print $5}\'';
1733
		}
1734
		if (isset($commandline)) {
1735
			$output = trim(`$commandline`);
1736
			if (ctype_digit($output)) {
1737
				$filesize = (float) $output;
1738
			}
1739
		}
1740
		return $filesize;
1741
	}
1742
1743
	/**
1744
	 * @param string $filename
1745
	 *
1746
	 * @return string|false
1747
	 */
1748
	public static function truepath($filename) {
1749
		// 2017-11-08: this could use some improvement, patches welcome
1750
		if (preg_match('#^(\\\\\\\\|//)[a-z0-9]#i', $filename, $matches)) {
1751
			// PHP's built-in realpath function does not work on UNC Windows shares
1752
			$goodpath = array();
1753
			foreach (explode('/', str_replace('\\', '/', $filename)) as $part) {
1754
				if ($part == '.') {
1755
					continue;
1756
				}
1757
				if ($part == '..') {
1758
					if (count($goodpath)) {
1759
						array_pop($goodpath);
1760
					} else {
1761
						// cannot step above this level, already at top level
1762
						return false;
1763
					}
1764
				} else {
1765
					$goodpath[] = $part;
1766
				}
1767
			}
1768
			return implode(DIRECTORY_SEPARATOR, $goodpath);
1769
		}
1770
		return realpath($filename);
1771
	}
1772
1773
	/**
1774
	 * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268)
1775
	 *
1776
	 * @param string $path A path.
1777
	 * @param string $suffix If the name component ends in suffix this will also be cut off.
1778
	 *
1779
	 * @return string
1780
	 */
1781
	public static function mb_basename($path, $suffix = null) {
1782
		$splited = preg_split('#/#', rtrim($path, '/ '));
1783
		return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1);
1784
	}
1785
1786
}
1787