run:R W Run
54.21 KB
2026-03-11 16:18:51
R W Run
79.05 KB
2026-03-11 16:18:51
R W Run
1.36 KB
2026-03-11 16:18:51
R W Run
133.61 KB
2026-03-11 16:18:51
R W Run
26.5 KB
2026-03-11 16:18:51
R W Run
104.64 KB
2026-03-11 16:18:51
R W Run
164.97 KB
2026-03-11 16:18:51
R W Run
136.53 KB
2026-03-11 16:18:51
R W Run
38.46 KB
2026-03-11 16:18:51
R W Run
10.63 KB
2026-03-11 16:18:51
R W Run
19.23 KB
2026-03-11 16:18:51
R W Run
104.5 KB
2026-03-11 16:18:51
R W Run
42.74 KB
2026-03-11 16:18:51
R W Run
18.63 KB
2026-03-11 16:18:51
R W Run
14.7 KB
2026-03-11 16:18:51
R W Run
151.2 KB
2026-03-11 16:18:51
R W Run
11.75 KB
2026-03-11 16:18:51
R W Run
25.71 KB
2026-03-11 16:18:51
R W Run
error_log
📄getid3.lib.php
1<?php
2
3/////////////////////////////////////////////////////////////////
4/// getID3() by James Heinrich <info@getid3.org> //
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
14if (!defined('GETID3_LIBXML_OPTIONS') && defined('LIBXML_VERSION')) {
15 if (LIBXML_VERSION >= 20621) {
16 define('GETID3_LIBXML_OPTIONS', LIBXML_NONET | LIBXML_NOWARNING | LIBXML_COMPACT);
17 } else {
18 define('GETID3_LIBXML_OPTIONS', LIBXML_NONET | LIBXML_NOWARNING);
19 }
20}
21
22class getid3_lib
23{
24 /**
25 * @param string $string
26 * @param bool $hex
27 * @param bool $spaces
28 * @param string|bool $htmlencoding
29 *
30 * @return string
31 */
32 public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') {
33 $returnstring = '';
34 for ($i = 0; $i < strlen($string); $i++) {
35 if ($hex) {
36 $returnstring .= str_pad(dechex(ord($string[$i])), 2, '0', STR_PAD_LEFT);
37 } else {
38 $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string[$i]) ? $string[$i] : '¤');
39 }
40 if ($spaces) {
41 $returnstring .= ' ';
42 }
43 }
44 if (!empty($htmlencoding)) {
45 if ($htmlencoding === true) {
46 $htmlencoding = 'UTF-8'; // prior to getID3 v1.9.0 the function's 4th parameter was boolean
47 }
48 $returnstring = htmlentities($returnstring, ENT_QUOTES, $htmlencoding);
49 }
50 return $returnstring;
51 }
52
53 /**
54 * Truncates a floating-point number at the decimal point.
55 *
56 * @param float $floatnumber
57 *
58 * @return float|int returns int (if possible, otherwise float)
59 */
60 public static function trunc($floatnumber) {
61 if ($floatnumber >= 1) {
62 $truncatednumber = floor($floatnumber);
63 } elseif ($floatnumber <= -1) {
64 $truncatednumber = ceil($floatnumber);
65 } else {
66 $truncatednumber = 0;
67 }
68 if (self::intValueSupported($truncatednumber)) {
69 $truncatednumber = (int) $truncatednumber;
70 }
71 return $truncatednumber;
72 }
73
74 /**
75 * @param int|null $variable
76 * @param-out int $variable
77 * @param int $increment
78 *
79 * @return bool
80 */
81 public static function safe_inc(&$variable, $increment=1) {
82 if (isset($variable)) {
83 $variable += $increment;
84 } else {
85 $variable = $increment;
86 }
87 return true;
88 }
89
90 /**
91 * @param int|float $floatnum
92 *
93 * @return int|float
94 */
95 public static function CastAsInt($floatnum) {
96 // convert to float if not already
97 $floatnum = (float) $floatnum;
98
99 // convert a float to type int, only if possible
100 if (self::trunc($floatnum) == $floatnum) {
101 // it's not floating point
102 if (self::intValueSupported($floatnum)) {
103 // it's within int range
104 $floatnum = (int) $floatnum;
105 }
106 }
107 return $floatnum;
108 }
109
110 /**
111 * @param int $num
112 *
113 * @return bool
114 */
115 public static function intValueSupported($num) {
116 // check if integers are 64-bit
117 static $hasINT64 = null;
118 if ($hasINT64 === null) { // 10x faster than is_null()
119 /** @var int|float|object $bigInt */
120 $bigInt = pow(2, 31);
121 $hasINT64 = is_int($bigInt); // 32-bit int are limited to (2^31)-1
122 if (!$hasINT64 && !defined('PHP_INT_MIN')) {
123 define('PHP_INT_MIN', ~PHP_INT_MAX);
124 }
125 }
126 // if integers are 64-bit - no other check required
127 if ($hasINT64 || (($num <= PHP_INT_MAX) && ($num >= PHP_INT_MIN))) {
128 return true;
129 }
130 return false;
131 }
132
133 /**
134 * Perform a division, guarding against division by zero
135 *
136 * @param float|int $numerator
137 * @param float|int $denominator
138 * @param float|int $fallback
139 * @return float|int
140 */
141 public static function SafeDiv($numerator, $denominator, $fallback = 0) {
142 return $denominator ? $numerator / $denominator : $fallback;
143 }
144
145 /**
146 * @param string $fraction
147 *
148 * @return float
149 */
150 public static function DecimalizeFraction($fraction) {
151 list($numerator, $denominator) = explode('/', $fraction);
152 return (int) $numerator / ($denominator ? $denominator : 1);
153 }
154
155 /**
156 * @param string $binarynumerator
157 *
158 * @return float
159 */
160 public static function DecimalBinary2Float($binarynumerator) {
161 $numerator = self::Bin2Dec($binarynumerator);
162 $denominator = self::Bin2Dec('1'.str_repeat('0', strlen($binarynumerator)));
163 return ($numerator / $denominator);
164 }
165
166 /**
167 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
168 *
169 * @param string $binarypointnumber
170 * @param int $maxbits
171 *
172 * @return array
173 */
174 public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) {
175 if (strpos($binarypointnumber, '.') === false) {
176 $binarypointnumber = '0.'.$binarypointnumber;
177 } elseif ($binarypointnumber[0] == '.') {
178 $binarypointnumber = '0'.$binarypointnumber;
179 }
180 $exponent = 0;
181 while (($binarypointnumber[0] != '1') || (substr($binarypointnumber, 1, 1) != '.')) {
182 if (substr($binarypointnumber, 1, 1) == '.') {
183 $exponent--;
184 $binarypointnumber = substr($binarypointnumber, 2, 1).'.'.substr($binarypointnumber, 3);
185 } else {
186 $pointpos = strpos($binarypointnumber, '.');
187 $exponent += ($pointpos - 1);
188 $binarypointnumber = str_replace('.', '', $binarypointnumber);
189 $binarypointnumber = $binarypointnumber[0].'.'.substr($binarypointnumber, 1);
190 }
191 }
192 $binarypointnumber = str_pad(substr($binarypointnumber, 0, $maxbits + 2), $maxbits + 2, '0', STR_PAD_RIGHT);
193 return array('normalized'=>$binarypointnumber, 'exponent'=>(int) $exponent);
194 }
195
196 /**
197 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html
198 *
199 * @param float $floatvalue
200 *
201 * @return string
202 */
203 public static function Float2BinaryDecimal($floatvalue) {
204 $maxbits = 128; // to how many bits of precision should the calculations be taken?
205 $intpart = self::trunc($floatvalue);
206 $floatpart = abs($floatvalue - $intpart);
207 $pointbitstring = '';
208 while (($floatpart != 0) && (strlen($pointbitstring) < $maxbits)) {
209 $floatpart *= 2;
210 $pointbitstring .= (string) self::trunc($floatpart);
211 $floatpart -= self::trunc($floatpart);
212 }
213 $binarypointnumber = decbin($intpart).'.'.$pointbitstring;
214 return $binarypointnumber;
215 }
216
217 /**
218 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html
219 *
220 * @param float $floatvalue
221 * @param int $bits
222 *
223 * @return string|false
224 */
225 public static function Float2String($floatvalue, $bits) {
226 $exponentbits = 0;
227 $fractionbits = 0;
228 switch ($bits) {
229 case 32:
230 $exponentbits = 8;
231 $fractionbits = 23;
232 break;
233
234 case 64:
235 $exponentbits = 11;
236 $fractionbits = 52;
237 break;
238
239 default:
240 return false;
241 }
242 if ($floatvalue >= 0) {
243 $signbit = '0';
244 } else {
245 $signbit = '1';
246 }
247 $normalizedbinary = self::NormalizeBinaryPoint(self::Float2BinaryDecimal($floatvalue), $fractionbits);
248 $biasedexponent = pow(2, $exponentbits - 1) - 1 + $normalizedbinary['exponent']; // (127 or 1023) +/- exponent
249 $exponentbitstring = str_pad(decbin($biasedexponent), $exponentbits, '0', STR_PAD_LEFT);
250 $fractionbitstring = str_pad(substr($normalizedbinary['normalized'], 2), $fractionbits, '0', STR_PAD_RIGHT);
251
252 return self::BigEndian2String(self::Bin2Dec($signbit.$exponentbitstring.$fractionbitstring), $bits % 8, false);
253 }
254
255 /**
256 * @param string $byteword
257 *
258 * @return float|false
259 */
260 public static function LittleEndian2Float($byteword) {
261 return self::BigEndian2Float(strrev($byteword));
262 }
263
264 /**
265 * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic
266 *
267 * @link https://web.archive.org/web/20120325162206/http://www.psc.edu/general/software/packages/ieee/ieee.php
268 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html
269 *
270 * @param string $byteword
271 *
272 * @return float|false
273 */
274 public static function BigEndian2Float($byteword) {
275 $bitword = self::BigEndian2Bin($byteword);
276 if (!$bitword) {
277 return 0;
278 }
279 $signbit = $bitword[0];
280 $floatvalue = 0;
281 $exponentbits = 0;
282 $fractionbits = 0;
283
284 switch (strlen($byteword) * 8) {
285 case 32:
286 $exponentbits = 8;
287 $fractionbits = 23;
288 break;
289
290 case 64:
291 $exponentbits = 11;
292 $fractionbits = 52;
293 break;
294
295 case 80:
296 // 80-bit Apple SANE format
297 // http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/
298 $exponentstring = substr($bitword, 1, 15);
299 $isnormalized = intval($bitword[16]);
300 $fractionstring = substr($bitword, 17, 63);
301 $exponent = pow(2, self::Bin2Dec($exponentstring) - 16383);
302 $fraction = $isnormalized + self::DecimalBinary2Float($fractionstring);
303 $floatvalue = $exponent * $fraction;
304 if ($signbit == '1') {
305 $floatvalue *= -1;
306 }
307 return $floatvalue;
308
309 default:
310 return false;
311 }
312 $exponentstring = substr($bitword, 1, $exponentbits);
313 $fractionstring = substr($bitword, $exponentbits + 1, $fractionbits);
314 $exponent = self::Bin2Dec($exponentstring);
315 $fraction = self::Bin2Dec($fractionstring);
316
317 if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) {
318 // Not a Number
319 $floatvalue = NAN;
320 } elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) {
321 if ($signbit == '1') {
322 $floatvalue = -INF;
323 } else {
324 $floatvalue = INF;
325 }
326 } elseif (($exponent == 0) && ($fraction == 0)) {
327 if ($signbit == '1') {
328 $floatvalue = -0.0;
329 } else {
330 $floatvalue = 0.0;
331 }
332 } elseif (($exponent == 0) && ($fraction != 0)) {
333 // These are 'unnormalized' values
334 $floatvalue = pow(2, (-1 * (pow(2, $exponentbits - 1) - 2))) * self::DecimalBinary2Float($fractionstring);
335 if ($signbit == '1') {
336 $floatvalue *= -1;
337 }
338 } elseif ($exponent != 0) {
339 $floatvalue = pow(2, ($exponent - (pow(2, $exponentbits - 1) - 1))) * (1 + self::DecimalBinary2Float($fractionstring));
340 if ($signbit == '1') {
341 $floatvalue *= -1;
342 }
343 }
344 return (float) $floatvalue;
345 }
346
347 /**
348 * @param string $byteword
349 * @param bool $synchsafe
350 * @param bool $signed
351 *
352 * @return int|float|false
353 * @throws Exception
354 */
355 public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) {
356 $intvalue = 0;
357 $bytewordlen = strlen($byteword);
358 if ($bytewordlen == 0) {
359 return false;
360 }
361 for ($i = 0; $i < $bytewordlen; $i++) {
362 if ($synchsafe) { // disregard MSB, effectively 7-bit bytes
363 //$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7); // faster, but runs into problems past 2^31 on 32-bit systems
364 $intvalue += (ord($byteword[$i]) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7);
365 } else {
366 $intvalue += ord($byteword[$i]) * pow(256, ($bytewordlen - 1 - $i));
367 }
368 }
369 if ($signed && !$synchsafe) {
370 // synchsafe ints are not allowed to be signed
371 if ($bytewordlen <= PHP_INT_SIZE) {
372 $signMaskBit = 0x80 << (8 * ($bytewordlen - 1));
373 if ($intvalue & $signMaskBit) {
374 $intvalue = 0 - ($intvalue & ($signMaskBit - 1));
375 }
376 } else {
377 throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits ('.strlen($byteword).') in self::BigEndian2Int()');
378 }
379 }
380 return self::CastAsInt($intvalue);
381 }
382
383 /**
384 * @param string $byteword
385 * @param bool $signed
386 *
387 * @return int|float|false
388 */
389 public static function LittleEndian2Int($byteword, $signed=false) {
390 return self::BigEndian2Int(strrev($byteword), false, $signed);
391 }
392
393 /**
394 * @param string $byteword
395 *
396 * @return string
397 */
398 public static function LittleEndian2Bin($byteword) {
399 return self::BigEndian2Bin(strrev($byteword));
400 }
401
402 /**
403 * @param string $byteword
404 *
405 * @return string
406 */
407 public static function BigEndian2Bin($byteword) {
408 $binvalue = '';
409 $bytewordlen = strlen($byteword);
410 for ($i = 0; $i < $bytewordlen; $i++) {
411 $binvalue .= str_pad(decbin(ord($byteword[$i])), 8, '0', STR_PAD_LEFT);
412 }
413 return $binvalue;
414 }
415
416 /**
417 * @param int $number
418 * @param int $minbytes
419 * @param bool $synchsafe
420 * @param bool $signed
421 *
422 * @return string
423 * @throws Exception
424 */
425 public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) {
426 if ($number < 0) {
427 throw new Exception('ERROR: self::BigEndian2String() does not support negative numbers');
428 }
429 $maskbyte = (($synchsafe || $signed) ? 0x7F : 0xFF);
430 $intstring = '';
431 if ($signed) {
432 if ($minbytes > PHP_INT_SIZE) {
433 throw new Exception('ERROR: Cannot have signed integers larger than '.(8 * PHP_INT_SIZE).'-bits in self::BigEndian2String()');
434 }
435 $number = $number & (0x80 << (8 * ($minbytes - 1)));
436 }
437 while ($number != 0) {
438 $quotient = ($number / ($maskbyte + 1));
439 $intstring = chr(ceil(($quotient - floor($quotient)) * $maskbyte)).$intstring;
440 $number = floor($quotient);
441 }
442 return str_pad($intstring, $minbytes, "\x00", STR_PAD_LEFT);
443 }
444
445 /**
446 * @param int|string $number
447 *
448 * @return string
449 */
450 public static function Dec2Bin($number) {
451 if (!is_numeric($number)) {
452 // https://github.com/JamesHeinrich/getID3/issues/299
453 trigger_error('TypeError: Dec2Bin(): Argument #1 ($number) must be numeric, '.gettype($number).' given', E_USER_WARNING);
454 return '';
455 }
456 $bytes = array();
457 while ($number >= 256) {
458 $bytes[] = (int) (($number / 256) - (floor($number / 256))) * 256;
459 $number = floor($number / 256);
460 }
461 $bytes[] = (int) $number;
462 $binstring = '';
463 foreach ($bytes as $i => $byte) {
464 $binstring = (($i == count($bytes) - 1) ? decbin($byte) : str_pad(decbin($byte), 8, '0', STR_PAD_LEFT)).$binstring;
465 }
466 return $binstring;
467 }
468
469 /**
470 * @param string $binstring
471 * @param bool $signed
472 *
473 * @return int|float
474 */
475 public static function Bin2Dec($binstring, $signed=false) {
476 $signmult = 1;
477 if ($signed) {
478 if ($binstring[0] == '1') {
479 $signmult = -1;
480 }
481 $binstring = substr($binstring, 1);
482 }
483 $decvalue = 0;
484 for ($i = 0; $i < strlen($binstring); $i++) {
485 $decvalue += ((int) substr($binstring, strlen($binstring) - $i - 1, 1)) * pow(2, $i);
486 }
487 return self::CastAsInt($decvalue * $signmult);
488 }
489
490 /**
491 * @param string $binstring
492 *
493 * @return string
494 */
495 public static function Bin2String($binstring) {
496 // return 'hi' for input of '0110100001101001'
497 $string = '';
498 $binstringreversed = strrev($binstring);
499 for ($i = 0; $i < strlen($binstringreversed); $i += 8) {
500 $string = chr(self::Bin2Dec(strrev(substr($binstringreversed, $i, 8)))).$string;
501 }
502 return $string;
503 }
504
505 /**
506 * @param int $number
507 * @param int $minbytes
508 * @param bool $synchsafe
509 *
510 * @return string
511 */
512 public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) {
513 $intstring = '';
514 while ($number > 0) {
515 if ($synchsafe) {
516 $intstring = $intstring.chr($number & 127);
517 $number >>= 7;
518 } else {
519 $intstring = $intstring.chr($number & 255);
520 $number >>= 8;
521 }
522 }
523 return str_pad($intstring, $minbytes, "\x00", STR_PAD_RIGHT);
524 }
525
526 /**
527 * @param mixed $array1
528 * @param mixed $array2
529 *
530 * @return array|false
531 */
532 public static function array_merge_clobber($array1, $array2) {
533 // written by kcØhireability*com
534 // taken from http://www.php.net/manual/en/function.array-merge-recursive.php
535 if (!is_array($array1) || !is_array($array2)) {
536 return false;
537 }
538 $newarray = $array1;
539 foreach ($array2 as $key => $val) {
540 if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
541 $newarray[$key] = self::array_merge_clobber($newarray[$key], $val);
542 } else {
543 $newarray[$key] = $val;
544 }
545 }
546 return $newarray;
547 }
548
549 /**
550 * @param mixed $array1
551 * @param mixed $array2
552 *
553 * @return array|false
554 */
555 public static function array_merge_noclobber($array1, $array2) {
556 if (!is_array($array1) || !is_array($array2)) {
557 return false;
558 }
559 $newarray = $array1;
560 foreach ($array2 as $key => $val) {
561 if (is_array($val) && isset($newarray[$key]) && is_array($newarray[$key])) {
562 $newarray[$key] = self::array_merge_noclobber($newarray[$key], $val);
563 } elseif (!isset($newarray[$key])) {
564 $newarray[$key] = $val;
565 }
566 }
567 return $newarray;
568 }
569
570 /**
571 * @param mixed $array1
572 * @param mixed $array2
573 *
574 * @return array|false|null
575 */
576 public static function flipped_array_merge_noclobber($array1, $array2) {
577 if (!is_array($array1) || !is_array($array2)) {
578 return false;
579 }
580 # naturally, this only works non-recursively
581 $newarray = array_flip($array1);
582 foreach (array_flip($array2) as $key => $val) {
583 if (!isset($newarray[$key])) {
584 $newarray[$key] = count($newarray);
585 }
586 }
587 return array_flip($newarray);
588 }
589
590 /**
591 * @param array $theArray
592 *
593 * @return bool
594 */
595 public static function ksort_recursive(&$theArray) {
596 ksort($theArray);
597 foreach ($theArray as $key => $value) {
598 if (is_array($value)) {
599 self::ksort_recursive($theArray[$key]);
600 }
601 }
602 return true;
603 }
604
605 /**
606 * @param string $filename
607 * @param int $numextensions
608 *
609 * @return string
610 */
611 public static function fileextension($filename, $numextensions=1) {
612 if (strstr($filename, '.')) {
613 $reversedfilename = strrev($filename);
614 $offset = 0;
615 for ($i = 0; $i < $numextensions; $i++) {
616 $offset = strpos($reversedfilename, '.', $offset + 1);
617 if ($offset === false) {
618 return '';
619 }
620 }
621 return strrev(substr($reversedfilename, 0, $offset));
622 }
623 return '';
624 }
625
626 /**
627 * @param int $seconds
628 *
629 * @return string
630 */
631 public static function PlaytimeString($seconds) {
632 $sign = (($seconds < 0) ? '-' : '');
633 $seconds = round(abs($seconds));
634 $H = (int) floor( $seconds / 3600);
635 $M = (int) floor(($seconds - (3600 * $H) ) / 60);
636 $S = (int) round( $seconds - (3600 * $H) - (60 * $M) );
637 return $sign.($H ? $H.':' : '').($H ? str_pad($M, 2, '0', STR_PAD_LEFT) : intval($M)).':'.str_pad($S, 2, 0, STR_PAD_LEFT);
638 }
639
640 /**
641 * @param int $macdate
642 *
643 * @return int|float
644 */
645 public static function DateMac2Unix($macdate) {
646 // Macintosh timestamp: seconds since 00:00h January 1, 1904
647 // UNIX timestamp: seconds since 00:00h January 1, 1970
648 return self::CastAsInt($macdate - 2082844800);
649 }
650
651 /**
652 * @param string $rawdata
653 *
654 * @return float
655 */
656 public static function FixedPoint8_8($rawdata) {
657 return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8));
658 }
659
660 /**
661 * @param string $rawdata
662 *
663 * @return float
664 */
665 public static function FixedPoint16_16($rawdata) {
666 return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16));
667 }
668
669 /**
670 * @param string $rawdata
671 *
672 * @return float
673 */
674 public static function FixedPoint2_30($rawdata) {
675 $binarystring = self::BigEndian2Bin($rawdata);
676 return self::Bin2Dec(substr($binarystring, 0, 2)) + (float) (self::Bin2Dec(substr($binarystring, 2, 30)) / pow(2, 30));
677 }
678
679
680 /**
681 * @param string $ArrayPath
682 * @param string $Separator
683 * @param mixed $Value
684 *
685 * @return array
686 */
687 public static function CreateDeepArray($ArrayPath, $Separator, $Value) {
688 // assigns $Value to a nested array path:
689 // $foo = self::CreateDeepArray('/path/to/my', '/', 'file.txt')
690 // is the same as:
691 // $foo = array('path'=>array('to'=>'array('my'=>array('file.txt'))));
692 // or
693 // $foo['path']['to']['my'] = 'file.txt';
694 $ArrayPath = ltrim($ArrayPath, $Separator);
695 $ReturnedArray = array();
696 if (($pos = strpos($ArrayPath, $Separator)) !== false) {
697 $ReturnedArray[substr($ArrayPath, 0, $pos)] = self::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value);
698 } else {
699 $ReturnedArray[$ArrayPath] = $Value;
700 }
701 return $ReturnedArray;
702 }
703
704 /**
705 * @param array $arraydata
706 * @param bool $returnkey
707 *
708 * @return int|false
709 */
710 public static function array_max($arraydata, $returnkey=false) {
711 $maxvalue = false;
712 $maxkey = false;
713 foreach ($arraydata as $key => $value) {
714 if (!is_array($value)) {
715 if (($maxvalue === false) || ($value > $maxvalue)) {
716 $maxvalue = $value;
717 $maxkey = $key;
718 }
719 }
720 }
721 return ($returnkey ? $maxkey : $maxvalue);
722 }
723
724 /**
725 * @param array $arraydata
726 * @param bool $returnkey
727 *
728 * @return int|false
729 */
730 public static function array_min($arraydata, $returnkey=false) {
731 $minvalue = false;
732 $minkey = false;
733 foreach ($arraydata as $key => $value) {
734 if (!is_array($value)) {
735 if (($minvalue === false) || ($value < $minvalue)) {
736 $minvalue = $value;
737 $minkey = $key;
738 }
739 }
740 }
741 return ($returnkey ? $minkey : $minvalue);
742 }
743
744 /**
745 * @param string $XMLstring
746 *
747 * @return array|false
748 */
749 public static function XML2array($XMLstring) {
750 if (function_exists('simplexml_load_string')) {
751 if (PHP_VERSION_ID < 80000) {
752 if (function_exists('libxml_disable_entity_loader')) {
753 // http://websec.io/2012/08/27/Preventing-XEE-in-PHP.html
754 // https://core.trac.wordpress.org/changeset/29378
755 // This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading is
756 // disabled by default, but is still needed when LIBXML_NOENT is used.
757 $loader = @libxml_disable_entity_loader(true);
758 $XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', GETID3_LIBXML_OPTIONS);
759 $return = self::SimpleXMLelement2array($XMLobject);
760 @libxml_disable_entity_loader($loader);
761 return $return;
762 }
763 } else {
764 $allow = false;
765 if (defined('LIBXML_VERSION') && (LIBXML_VERSION >= 20900)) {
766 // https://www.php.net/manual/en/function.libxml-disable-entity-loader.php
767 // "as of libxml 2.9.0 entity substitution is disabled by default, so there is no need to disable the loading
768 // of external entities, unless there is the need to resolve internal entity references with LIBXML_NOENT."
769 $allow = true;
770 } elseif (function_exists('libxml_set_external_entity_loader')) {
771 libxml_set_external_entity_loader(function () { return null; }); // https://www.zend.com/blog/cve-2023-3823
772 $allow = true;
773 }
774 if ($allow) {
775 $XMLobject = simplexml_load_string($XMLstring, 'SimpleXMLElement', GETID3_LIBXML_OPTIONS);
776 $return = self::SimpleXMLelement2array($XMLobject);
777 return $return;
778 }
779 }
780 }
781 return false;
782 }
783
784 /**
785 * @param SimpleXMLElement|array|mixed $XMLobject
786 *
787 * @return mixed
788 */
789 public static function SimpleXMLelement2array($XMLobject) {
790 if (!is_object($XMLobject) && !is_array($XMLobject)) {
791 return $XMLobject;
792 }
793 $XMLarray = $XMLobject instanceof SimpleXMLElement ? get_object_vars($XMLobject) : $XMLobject;
794 foreach ($XMLarray as $key => $value) {
795 $XMLarray[$key] = self::SimpleXMLelement2array($value);
796 }
797 return $XMLarray;
798 }
799
800 /**
801 * Returns checksum for a file from starting position to absolute end position.
802 *
803 * @param string $file
804 * @param int $offset
805 * @param int $end
806 * @param string $algorithm
807 *
808 * @return string|false
809 * @throws getid3_exception
810 */
811 public static function hash_data($file, $offset, $end, $algorithm) {
812 if (!self::intValueSupported($end)) {
813 return false;
814 }
815 if (!in_array($algorithm, array('md5', 'sha1'))) {
816 throw new getid3_exception('Invalid algorithm ('.$algorithm.') in self::hash_data()');
817 }
818
819 $size = $end - $offset;
820
821 $fp = fopen($file, 'rb');
822 fseek($fp, $offset);
823 $ctx = hash_init($algorithm);
824 while ($size > 0) {
825 $buffer = fread($fp, min($size, getID3::FREAD_BUFFER_SIZE));
826 hash_update($ctx, $buffer);
827 $size -= getID3::FREAD_BUFFER_SIZE;
828 }
829 $hash = hash_final($ctx);
830 fclose($fp);
831
832 return $hash;
833 }
834
835 /**
836 * @param string $filename_source
837 * @param string $filename_dest
838 * @param int $offset
839 * @param int $length
840 *
841 * @return bool
842 * @throws Exception
843 *
844 * @deprecated Unused, may be removed in future versions of getID3
845 */
846 public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) {
847 if (!self::intValueSupported($offset + $length)) {
848 throw new Exception('cannot copy file portion, it extends beyond the '.round(PHP_INT_MAX / 1073741824).'GB limit');
849 }
850 if (is_readable($filename_source) && is_file($filename_source) && ($fp_src = fopen($filename_source, 'rb'))) {
851 if (($fp_dest = fopen($filename_dest, 'wb'))) {
852 if (fseek($fp_src, $offset) == 0) {
853 $byteslefttowrite = $length;
854 while (($byteslefttowrite > 0) && ($buffer = fread($fp_src, min($byteslefttowrite, getID3::FREAD_BUFFER_SIZE)))) {
855 $byteswritten = fwrite($fp_dest, $buffer, $byteslefttowrite);
856 $byteslefttowrite -= $byteswritten;
857 }
858 fclose($fp_dest);
859 return true;
860 } else {
861 fclose($fp_src);
862 throw new Exception('failed to seek to offset '.$offset.' in '.$filename_source);
863 }
864 } else {
865 throw new Exception('failed to create file for writing '.$filename_dest);
866 }
867 } else {
868 throw new Exception('failed to open file for reading '.$filename_source);
869 }
870 }
871
872 /**
873 * @param int $charval
874 *
875 * @return string
876 */
877 public static function iconv_fallback_int_utf8($charval) {
878 if ($charval < 128) {
879 // 0bbbbbbb
880 $newcharstring = chr($charval);
881 } elseif ($charval < 2048) {
882 // 110bbbbb 10bbbbbb
883 $newcharstring = chr(($charval >> 6) | 0xC0);
884 $newcharstring .= chr(($charval & 0x3F) | 0x80);
885 } elseif ($charval < 65536) {
886 // 1110bbbb 10bbbbbb 10bbbbbb
887 $newcharstring = chr(($charval >> 12) | 0xE0);
888 $newcharstring .= chr(($charval >> 6) | 0xC0);
889 $newcharstring .= chr(($charval & 0x3F) | 0x80);
890 } else {
891 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
892 $newcharstring = chr(($charval >> 18) | 0xF0);
893 $newcharstring .= chr(($charval >> 12) | 0xC0);
894 $newcharstring .= chr(($charval >> 6) | 0xC0);
895 $newcharstring .= chr(($charval & 0x3F) | 0x80);
896 }
897 return $newcharstring;
898 }
899
900 /**
901 * ISO-8859-1 => UTF-8
902 *
903 * @param string $string
904 * @param bool $bom
905 *
906 * @return string
907 */
908 public static function iconv_fallback_iso88591_utf8($string, $bom=false) {
909 $newcharstring = '';
910 if ($bom) {
911 $newcharstring .= "\xEF\xBB\xBF";
912 }
913 for ($i = 0; $i < strlen($string); $i++) {
914 $charval = ord($string[$i]);
915 $newcharstring .= self::iconv_fallback_int_utf8($charval);
916 }
917 return $newcharstring;
918 }
919
920 /**
921 * ISO-8859-1 => UTF-16BE
922 *
923 * @param string $string
924 * @param bool $bom
925 *
926 * @return string
927 */
928 public static function iconv_fallback_iso88591_utf16be($string, $bom=false) {
929 $newcharstring = '';
930 if ($bom) {
931 $newcharstring .= "\xFE\xFF";
932 }
933 for ($i = 0; $i < strlen($string); $i++) {
934 $newcharstring .= "\x00".$string[$i];
935 }
936 return $newcharstring;
937 }
938
939 /**
940 * ISO-8859-1 => UTF-16LE
941 *
942 * @param string $string
943 * @param bool $bom
944 *
945 * @return string
946 */
947 public static function iconv_fallback_iso88591_utf16le($string, $bom=false) {
948 $newcharstring = '';
949 if ($bom) {
950 $newcharstring .= "\xFF\xFE";
951 }
952 for ($i = 0; $i < strlen($string); $i++) {
953 $newcharstring .= $string[$i]."\x00";
954 }
955 return $newcharstring;
956 }
957
958 /**
959 * ISO-8859-1 => UTF-16LE (BOM)
960 *
961 * @param string $string
962 *
963 * @return string
964 */
965 public static function iconv_fallback_iso88591_utf16($string) {
966 return self::iconv_fallback_iso88591_utf16le($string, true);
967 }
968
969 /**
970 * UTF-8 => ISO-8859-1
971 *
972 * @param string $string
973 *
974 * @return string
975 */
976 public static function iconv_fallback_utf8_iso88591($string) {
977 $newcharstring = '';
978 $offset = 0;
979 $stringlength = strlen($string);
980 while ($offset < $stringlength) {
981 if ((ord($string[$offset]) | 0x07) == 0xF7) {
982 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
983 $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
984 ((ord($string[($offset + 1)]) & 0x3F) << 12) &
985 ((ord($string[($offset + 2)]) & 0x3F) << 6) &
986 (ord($string[($offset + 3)]) & 0x3F);
987 $offset += 4;
988 } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
989 // 1110bbbb 10bbbbbb 10bbbbbb
990 $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
991 ((ord($string[($offset + 1)]) & 0x3F) << 6) &
992 (ord($string[($offset + 2)]) & 0x3F);
993 $offset += 3;
994 } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
995 // 110bbbbb 10bbbbbb
996 $charval = ((ord($string[($offset + 0)]) & 0x1F) << 6) &
997 (ord($string[($offset + 1)]) & 0x3F);
998 $offset += 2;
999 } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
1000 // 0bbbbbbb
1001 $charval = ord($string[$offset]);
1002 $offset += 1;
1003 } else {
1004 // error? throw some kind of warning here?
1005 $charval = false;
1006 $offset += 1;
1007 }
1008 if ($charval !== false) {
1009 $newcharstring .= (($charval < 256) ? chr($charval) : '?');
1010 }
1011 }
1012 return $newcharstring;
1013 }
1014
1015 /**
1016 * UTF-8 => UTF-16BE
1017 *
1018 * @param string $string
1019 * @param bool $bom
1020 *
1021 * @return string
1022 */
1023 public static function iconv_fallback_utf8_utf16be($string, $bom=false) {
1024 $newcharstring = '';
1025 if ($bom) {
1026 $newcharstring .= "\xFE\xFF";
1027 }
1028 $offset = 0;
1029 $stringlength = strlen($string);
1030 while ($offset < $stringlength) {
1031 if ((ord($string[$offset]) | 0x07) == 0xF7) {
1032 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
1033 $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
1034 ((ord($string[($offset + 1)]) & 0x3F) << 12) &
1035 ((ord($string[($offset + 2)]) & 0x3F) << 6) &
1036 (ord($string[($offset + 3)]) & 0x3F);
1037 $offset += 4;
1038 } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
1039 // 1110bbbb 10bbbbbb 10bbbbbb
1040 $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
1041 ((ord($string[($offset + 1)]) & 0x3F) << 6) &
1042 (ord($string[($offset + 2)]) & 0x3F);
1043 $offset += 3;
1044 } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
1045 // 110bbbbb 10bbbbbb
1046 $charval = ((ord($string[($offset + 0)]) & 0x1F) << 6) &
1047 (ord($string[($offset + 1)]) & 0x3F);
1048 $offset += 2;
1049 } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
1050 // 0bbbbbbb
1051 $charval = ord($string[$offset]);
1052 $offset += 1;
1053 } else {
1054 // error? throw some kind of warning here?
1055 $charval = false;
1056 $offset += 1;
1057 }
1058 if ($charval !== false) {
1059 $newcharstring .= (($charval < 65536) ? self::BigEndian2String($charval, 2) : "\x00".'?');
1060 }
1061 }
1062 return $newcharstring;
1063 }
1064
1065 /**
1066 * UTF-8 => UTF-16LE
1067 *
1068 * @param string $string
1069 * @param bool $bom
1070 *
1071 * @return string
1072 */
1073 public static function iconv_fallback_utf8_utf16le($string, $bom=false) {
1074 $newcharstring = '';
1075 if ($bom) {
1076 $newcharstring .= "\xFF\xFE";
1077 }
1078 $offset = 0;
1079 $stringlength = strlen($string);
1080 while ($offset < $stringlength) {
1081 if ((ord($string[$offset]) | 0x07) == 0xF7) {
1082 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb
1083 $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) &
1084 ((ord($string[($offset + 1)]) & 0x3F) << 12) &
1085 ((ord($string[($offset + 2)]) & 0x3F) << 6) &
1086 (ord($string[($offset + 3)]) & 0x3F);
1087 $offset += 4;
1088 } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) {
1089 // 1110bbbb 10bbbbbb 10bbbbbb
1090 $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) &
1091 ((ord($string[($offset + 1)]) & 0x3F) << 6) &
1092 (ord($string[($offset + 2)]) & 0x3F);
1093 $offset += 3;
1094 } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) {
1095 // 110bbbbb 10bbbbbb
1096 $charval = ((ord($string[($offset + 0)]) & 0x1F) << 6) &
1097 (ord($string[($offset + 1)]) & 0x3F);
1098 $offset += 2;
1099 } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) {
1100 // 0bbbbbbb
1101 $charval = ord($string[$offset]);
1102 $offset += 1;
1103 } else {
1104 // error? maybe throw some warning here?
1105 $charval = false;
1106 $offset += 1;
1107 }
1108 if ($charval !== false) {
1109 $newcharstring .= (($charval < 65536) ? self::LittleEndian2String($charval, 2) : '?'."\x00");
1110 }
1111 }
1112 return $newcharstring;
1113 }
1114
1115 /**
1116 * UTF-8 => UTF-16LE (BOM)
1117 *
1118 * @param string $string
1119 *
1120 * @return string
1121 */
1122 public static function iconv_fallback_utf8_utf16($string) {
1123 return self::iconv_fallback_utf8_utf16le($string, true);
1124 }
1125
1126 /**
1127 * UTF-16BE => UTF-8
1128 *
1129 * @param string $string
1130 *
1131 * @return string
1132 */
1133 public static function iconv_fallback_utf16be_utf8($string) {
1134 if (substr($string, 0, 2) == "\xFE\xFF") {
1135 // strip BOM
1136 $string = substr($string, 2);
1137 }
1138 $newcharstring = '';
1139 for ($i = 0; $i < strlen($string); $i += 2) {
1140 $charval = self::BigEndian2Int(substr($string, $i, 2));
1141 $newcharstring .= self::iconv_fallback_int_utf8($charval);
1142 }
1143 return $newcharstring;
1144 }
1145
1146 /**
1147 * UTF-16LE => UTF-8
1148 *
1149 * @param string $string
1150 *
1151 * @return string
1152 */
1153 public static function iconv_fallback_utf16le_utf8($string) {
1154 if (substr($string, 0, 2) == "\xFF\xFE") {
1155 // strip BOM
1156 $string = substr($string, 2);
1157 }
1158 $newcharstring = '';
1159 for ($i = 0; $i < strlen($string); $i += 2) {
1160 $charval = self::LittleEndian2Int(substr($string, $i, 2));
1161 $newcharstring .= self::iconv_fallback_int_utf8($charval);
1162 }
1163 return $newcharstring;
1164 }
1165
1166 /**
1167 * UTF-16BE => ISO-8859-1
1168 *
1169 * @param string $string
1170 *
1171 * @return string
1172 */
1173 public static function iconv_fallback_utf16be_iso88591($string) {
1174 if (substr($string, 0, 2) == "\xFE\xFF") {
1175 // strip BOM
1176 $string = substr($string, 2);
1177 }
1178 $newcharstring = '';
1179 for ($i = 0; $i < strlen($string); $i += 2) {
1180 $charval = self::BigEndian2Int(substr($string, $i, 2));
1181 $newcharstring .= (($charval < 256) ? chr($charval) : '?');
1182 }
1183 return $newcharstring;
1184 }
1185
1186 /**
1187 * UTF-16LE => ISO-8859-1
1188 *
1189 * @param string $string
1190 *
1191 * @return string
1192 */
1193 public static function iconv_fallback_utf16le_iso88591($string) {
1194 if (substr($string, 0, 2) == "\xFF\xFE") {
1195 // strip BOM
1196 $string = substr($string, 2);
1197 }
1198 $newcharstring = '';
1199 for ($i = 0; $i < strlen($string); $i += 2) {
1200 $charval = self::LittleEndian2Int(substr($string, $i, 2));
1201 $newcharstring .= (($charval < 256) ? chr($charval) : '?');
1202 }
1203 return $newcharstring;
1204 }
1205
1206 /**
1207 * UTF-16 (BOM) => ISO-8859-1
1208 *
1209 * @param string $string
1210 *
1211 * @return string
1212 */
1213 public static function iconv_fallback_utf16_iso88591($string) {
1214 $bom = substr($string, 0, 2);
1215 if ($bom == "\xFE\xFF") {
1216 return self::iconv_fallback_utf16be_iso88591(substr($string, 2));
1217 } elseif ($bom == "\xFF\xFE") {
1218 return self::iconv_fallback_utf16le_iso88591(substr($string, 2));
1219 }
1220 return $string;
1221 }
1222
1223 /**
1224 * UTF-16 (BOM) => UTF-8
1225 *
1226 * @param string $string
1227 *
1228 * @return string
1229 */
1230 public static function iconv_fallback_utf16_utf8($string) {
1231 $bom = substr($string, 0, 2);
1232 if ($bom == "\xFE\xFF") {
1233 return self::iconv_fallback_utf16be_utf8(substr($string, 2));
1234 } elseif ($bom == "\xFF\xFE") {
1235 return self::iconv_fallback_utf16le_utf8(substr($string, 2));
1236 }
1237 return $string;
1238 }
1239
1240 /**
1241 * @param string $in_charset
1242 * @param string $out_charset
1243 * @param string $string
1244 *
1245 * @return string
1246 * @throws Exception
1247 */
1248 public static function iconv_fallback($in_charset, $out_charset, $string) {
1249
1250 if ($in_charset == $out_charset) {
1251 return $string;
1252 }
1253
1254 // mb_convert_encoding() available
1255 if (function_exists('mb_convert_encoding')) {
1256 if ((strtoupper($in_charset) == 'UTF-16') && (substr($string, 0, 2) != "\xFE\xFF") && (substr($string, 0, 2) != "\xFF\xFE")) {
1257 // if BOM missing, mb_convert_encoding will mishandle the conversion, assume UTF-16BE and prepend appropriate BOM
1258 $string = "\xFF\xFE".$string;
1259 }
1260 if ((strtoupper($in_charset) == 'UTF-16') && (strtoupper($out_charset) == 'UTF-8')) {
1261 if (($string == "\xFF\xFE") || ($string == "\xFE\xFF")) {
1262 // if string consists of only BOM, mb_convert_encoding will return the BOM unmodified
1263 return '';
1264 }
1265 }
1266 if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) {
1267 switch ($out_charset) {
1268 case 'ISO-8859-1':
1269 $converted_string = rtrim($converted_string, "\x00");
1270 break;
1271 }
1272 return $converted_string;
1273 }
1274 return $string;
1275
1276 // iconv() available
1277 } elseif (function_exists('iconv')) {
1278 if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) {
1279 switch ($out_charset) {
1280 case 'ISO-8859-1':
1281 $converted_string = rtrim($converted_string, "\x00");
1282 break;
1283 }
1284 return $converted_string;
1285 }
1286
1287 // iconv() may sometimes fail with "illegal character in input string" error message
1288 // and return an empty string, but returning the unconverted string is more useful
1289 return $string;
1290 }
1291
1292
1293 // neither mb_convert_encoding or iconv() is available
1294 static $ConversionFunctionList = array();
1295 if (empty($ConversionFunctionList)) {
1296 $ConversionFunctionList['ISO-8859-1']['UTF-8'] = 'iconv_fallback_iso88591_utf8';
1297 $ConversionFunctionList['ISO-8859-1']['UTF-16'] = 'iconv_fallback_iso88591_utf16';
1298 $ConversionFunctionList['ISO-8859-1']['UTF-16BE'] = 'iconv_fallback_iso88591_utf16be';
1299 $ConversionFunctionList['ISO-8859-1']['UTF-16LE'] = 'iconv_fallback_iso88591_utf16le';
1300 $ConversionFunctionList['UTF-8']['ISO-8859-1'] = 'iconv_fallback_utf8_iso88591';
1301 $ConversionFunctionList['UTF-8']['UTF-16'] = 'iconv_fallback_utf8_utf16';
1302 $ConversionFunctionList['UTF-8']['UTF-16BE'] = 'iconv_fallback_utf8_utf16be';
1303 $ConversionFunctionList['UTF-8']['UTF-16LE'] = 'iconv_fallback_utf8_utf16le';
1304 $ConversionFunctionList['UTF-16']['ISO-8859-1'] = 'iconv_fallback_utf16_iso88591';
1305 $ConversionFunctionList['UTF-16']['UTF-8'] = 'iconv_fallback_utf16_utf8';
1306 $ConversionFunctionList['UTF-16LE']['ISO-8859-1'] = 'iconv_fallback_utf16le_iso88591';
1307 $ConversionFunctionList['UTF-16LE']['UTF-8'] = 'iconv_fallback_utf16le_utf8';
1308 $ConversionFunctionList['UTF-16BE']['ISO-8859-1'] = 'iconv_fallback_utf16be_iso88591';
1309 $ConversionFunctionList['UTF-16BE']['UTF-8'] = 'iconv_fallback_utf16be_utf8';
1310 }
1311 if (isset($ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)])) {
1312 $ConversionFunction = $ConversionFunctionList[strtoupper($in_charset)][strtoupper($out_charset)];
1313 return self::$ConversionFunction($string);
1314 }
1315 throw new Exception('PHP does not has mb_convert_encoding() or iconv() support - cannot convert from '.$in_charset.' to '.$out_charset);
1316 }
1317
1318 /**
1319 * @param mixed $data
1320 * @param string $charset
1321 *
1322 * @return mixed
1323 */
1324 public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') {
1325 if (is_string($data)) {
1326 return self::MultiByteCharString2HTML($data, $charset);
1327 } elseif (is_array($data)) {
1328 $return_data = array();
1329 foreach ($data as $key => $value) {
1330 $return_data[$key] = self::recursiveMultiByteCharString2HTML($value, $charset);
1331 }
1332 return $return_data;
1333 }
1334 // integer, float, objects, resources, etc
1335 return $data;
1336 }
1337
1338 /**
1339 * @param string|int|float $string
1340 * @param string $charset
1341 *
1342 * @return string
1343 */
1344 public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') {
1345 $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string
1346 $HTMLstring = '';
1347
1348 switch (strtolower($charset)) {
1349 case '1251':
1350 case '1252':
1351 case '866':
1352 case '932':
1353 case '936':
1354 case '950':
1355 case 'big5':
1356 case 'big5-hkscs':
1357 case 'cp1251':
1358 case 'cp1252':
1359 case 'cp866':
1360 case 'euc-jp':
1361 case 'eucjp':
1362 case 'gb2312':
1363 case 'ibm866':
1364 case 'iso-8859-1':
1365 case 'iso-8859-15':
1366 case 'iso8859-1':
1367 case 'iso8859-15':
1368 case 'koi8-r':
1369 case 'koi8-ru':
1370 case 'koi8r':
1371 case 'shift_jis':
1372 case 'sjis':
1373 case 'win-1251':
1374 case 'windows-1251':
1375 case 'windows-1252':
1376 $HTMLstring = htmlentities($string, ENT_COMPAT, $charset);
1377 break;
1378
1379 case 'utf-8':
1380 $strlen = strlen($string);
1381 for ($i = 0; $i < $strlen; $i++) {
1382 $char_ord_val = ord($string[$i]);
1383 $charval = 0;
1384 if ($char_ord_val < 0x80) {
1385 $charval = $char_ord_val;
1386 } elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F && $i+3 < $strlen) {
1387 $charval = (($char_ord_val & 0x07) << 18);
1388 $charval += ((ord($string[++$i]) & 0x3F) << 12);
1389 $charval += ((ord($string[++$i]) & 0x3F) << 6);
1390 $charval += (ord($string[++$i]) & 0x3F);
1391 } elseif ((($char_ord_val & 0xE0) >> 5) == 0x07 && $i+2 < $strlen) {
1392 $charval = (($char_ord_val & 0x0F) << 12);
1393 $charval += ((ord($string[++$i]) & 0x3F) << 6);
1394 $charval += (ord($string[++$i]) & 0x3F);
1395 } elseif ((($char_ord_val & 0xC0) >> 6) == 0x03 && $i+1 < $strlen) {
1396 $charval = (($char_ord_val & 0x1F) << 6);
1397 $charval += (ord($string[++$i]) & 0x3F);
1398 }
1399 if (($charval >= 32) && ($charval <= 127)) {
1400 $HTMLstring .= htmlentities(chr($charval));
1401 } else {
1402 $HTMLstring .= '&#'.$charval.';';
1403 }
1404 }
1405 break;
1406
1407 case 'utf-16le':
1408 for ($i = 0; $i < strlen($string); $i += 2) {
1409 $charval = self::LittleEndian2Int(substr($string, $i, 2));
1410 if (($charval >= 32) && ($charval <= 127)) {
1411 $HTMLstring .= chr($charval);
1412 } else {
1413 $HTMLstring .= '&#'.$charval.';';
1414 }
1415 }
1416 break;
1417
1418 case 'utf-16be':
1419 for ($i = 0; $i < strlen($string); $i += 2) {
1420 $charval = self::BigEndian2Int(substr($string, $i, 2));
1421 if (($charval >= 32) && ($charval <= 127)) {
1422 $HTMLstring .= chr($charval);
1423 } else {
1424 $HTMLstring .= '&#'.$charval.';';
1425 }
1426 }
1427 break;
1428
1429 default:
1430 $HTMLstring = 'ERROR: Character set "'.$charset.'" not supported in MultiByteCharString2HTML()';
1431 break;
1432 }
1433 return $HTMLstring;
1434 }
1435
1436 /**
1437 * @param int $namecode
1438 *
1439 * @return string
1440 */
1441 public static function RGADnameLookup($namecode) {
1442 static $RGADname = array();
1443 if (empty($RGADname)) {
1444 $RGADname[0] = 'not set';
1445 $RGADname[1] = 'Track Gain Adjustment';
1446 $RGADname[2] = 'Album Gain Adjustment';
1447 }
1448
1449 return (isset($RGADname[$namecode]) ? $RGADname[$namecode] : '');
1450 }
1451
1452 /**
1453 * @param int $originatorcode
1454 *
1455 * @return string
1456 */
1457 public static function RGADoriginatorLookup($originatorcode) {
1458 static $RGADoriginator = array();
1459 if (empty($RGADoriginator)) {
1460 $RGADoriginator[0] = 'unspecified';
1461 $RGADoriginator[1] = 'pre-set by artist/producer/mastering engineer';
1462 $RGADoriginator[2] = 'set by user';
1463 $RGADoriginator[3] = 'determined automatically';
1464 }
1465
1466 return (isset($RGADoriginator[$originatorcode]) ? $RGADoriginator[$originatorcode] : '');
1467 }
1468
1469 /**
1470 * @param int $rawadjustment
1471 * @param int $signbit
1472 *
1473 * @return float
1474 */
1475 public static function RGADadjustmentLookup($rawadjustment, $signbit) {
1476 $adjustment = (float) $rawadjustment / 10;
1477 if ($signbit == 1) {
1478 $adjustment *= -1;
1479 }
1480 return $adjustment;
1481 }
1482
1483 /**
1484 * @param int $namecode
1485 * @param int $originatorcode
1486 * @param int $replaygain
1487 *
1488 * @return string
1489 */
1490 public static function RGADgainString($namecode, $originatorcode, $replaygain) {
1491 if ($replaygain < 0) {
1492 $signbit = '1';
1493 } else {
1494 $signbit = '0';
1495 }
1496 $storedreplaygain = intval(round($replaygain * 10));
1497 $gainstring = str_pad(decbin($namecode), 3, '0', STR_PAD_LEFT);
1498 $gainstring .= str_pad(decbin($originatorcode), 3, '0', STR_PAD_LEFT);
1499 $gainstring .= $signbit;
1500 $gainstring .= str_pad(decbin($storedreplaygain), 9, '0', STR_PAD_LEFT);
1501
1502 return $gainstring;
1503 }
1504
1505 /**
1506 * @param float $amplitude
1507 *
1508 * @return float
1509 */
1510 public static function RGADamplitude2dB($amplitude) {
1511 return 20 * log10($amplitude);
1512 }
1513
1514 /**
1515 * @param string $imgData
1516 * @param array $imageinfo
1517 *
1518 * @return array|false
1519 */
1520 public static function GetDataImageSize($imgData, &$imageinfo=array()) {
1521 if (PHP_VERSION_ID >= 50400) {
1522 $GetDataImageSize = @getimagesizefromstring($imgData, $imageinfo);
1523 if ($GetDataImageSize === false) {
1524 return false;
1525 }
1526 $GetDataImageSize['height'] = $GetDataImageSize[0];
1527 $GetDataImageSize['width'] = $GetDataImageSize[1];
1528 return $GetDataImageSize;
1529 }
1530 static $tempdir = '';
1531 if (empty($tempdir)) {
1532 if (function_exists('sys_get_temp_dir')) {
1533 $tempdir = sys_get_temp_dir(); // https://github.com/JamesHeinrich/getID3/issues/52
1534 }
1535
1536 // yes this is ugly, feel free to suggest a better way
1537 if (include_once(dirname(__FILE__).'/getid3.php')) {
1538 $getid3_temp = new getID3();
1539 if ($getid3_temp_tempdir = $getid3_temp->tempdir) {
1540 $tempdir = $getid3_temp_tempdir;
1541 }
1542 unset($getid3_temp, $getid3_temp_tempdir);
1543 }
1544 }
1545 $GetDataImageSize = false;
1546 if ($tempfilename = tempnam($tempdir, 'gI3')) {
1547 if (is_writable($tempfilename) && is_file($tempfilename) && ($tmp = fopen($tempfilename, 'wb'))) {
1548 fwrite($tmp, $imgData);
1549 fclose($tmp);
1550 $GetDataImageSize = @getimagesize($tempfilename, $imageinfo);
1551 if ($GetDataImageSize === false) {
1552 return false;
1553 }
1554 $GetDataImageSize['height'] = $GetDataImageSize[0];
1555 $GetDataImageSize['width'] = $GetDataImageSize[1];
1556 }
1557 unlink($tempfilename);
1558 }
1559 return $GetDataImageSize;
1560 }
1561
1562 /**
1563 * @param string $mime_type
1564 *
1565 * @return string
1566 */
1567 public static function ImageExtFromMime($mime_type) {
1568 // temporary way, works OK for now, but should be reworked in the future
1569 return str_replace(array('image/', 'x-', 'jpeg'), array('', '', 'jpg'), $mime_type);
1570 }
1571
1572 /**
1573 * @param array $ThisFileInfo
1574 * @param bool $option_tags_html default true (just as in the main getID3 class)
1575 *
1576 * @return bool
1577 */
1578 public static function CopyTagsToComments(&$ThisFileInfo, $option_tags_html=true) {
1579 // Copy all entries from ['tags'] into common ['comments']
1580 if (!empty($ThisFileInfo['tags'])) {
1581
1582 // Some tag types can only support limited character sets and may contain data in non-standard encoding (usually ID3v1)
1583 // and/or poorly-transliterated tag values that are also in tag formats that do support full-range character sets
1584 // To make the output more user-friendly, process the potentially-problematic tag formats last to enhance the chance that
1585 // the first entries in [comments] are the most correct and the "bad" ones (if any) come later.
1586 // https://github.com/JamesHeinrich/getID3/issues/338
1587 $processLastTagTypes = array('id3v1','riff');
1588 foreach ($processLastTagTypes as $processLastTagType) {
1589 if (isset($ThisFileInfo['tags'][$processLastTagType])) {
1590 // bubble ID3v1 to the end, if present to aid in detecting bad ID3v1 encodings
1591 $temp = $ThisFileInfo['tags'][$processLastTagType];
1592 unset($ThisFileInfo['tags'][$processLastTagType]);
1593 $ThisFileInfo['tags'][$processLastTagType] = $temp;
1594 unset($temp);
1595 }
1596 }
1597 foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) {
1598 foreach ($tagarray as $tagname => $tagdata) {
1599 foreach ($tagdata as $key => $value) {
1600 if (!empty($value)) {
1601 if (empty($ThisFileInfo['comments'][$tagname])) {
1602
1603 // fall through and append value
1604
1605 } elseif ($tagtype == 'id3v1') {
1606
1607 $newvaluelength = strlen(trim($value));
1608 foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
1609 $oldvaluelength = strlen(trim($existingvalue));
1610 if (($newvaluelength <= $oldvaluelength) && (substr($existingvalue, 0, $newvaluelength) == trim($value))) {
1611 // new value is identical but shorter-than (or equal-length to) one already in comments - skip
1612 break 2;
1613 }
1614
1615 if (function_exists('mb_convert_encoding')) {
1616 if (trim($value) == trim(substr(mb_convert_encoding($existingvalue, $ThisFileInfo['id3v1']['encoding'], $ThisFileInfo['encoding']), 0, 30))) {
1617 // value stored in ID3v1 appears to be probably the multibyte value transliterated (badly) into ISO-8859-1 in ID3v1.
1618 // As an example, Foobar2000 will do this if you tag a file with Chinese or Arabic or Cyrillic or something that doesn't fit into ISO-8859-1 the ID3v1 will consist of mostly "?" characters, one per multibyte unrepresentable character
1619 break 2;
1620 }
1621 }
1622 }
1623
1624 } elseif (!is_array($value)) {
1625
1626 $newvaluelength = strlen(trim($value));
1627 $newvaluelengthMB = mb_strlen(trim($value));
1628 foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) {
1629 $oldvaluelength = strlen(trim($existingvalue));
1630 $oldvaluelengthMB = mb_strlen(trim($existingvalue));
1631 if (($newvaluelengthMB == $oldvaluelengthMB) && ($existingvalue == getid3_lib::iconv_fallback('UTF-8', 'ASCII', $value))) {
1632 // https://github.com/JamesHeinrich/getID3/issues/338
1633 // check for tags containing extended characters that may have been forced into limited-character storage (e.g. UTF8 values into ASCII)
1634 // which will usually display unrepresentable characters as "?"
1635 $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
1636 break;
1637 }
1638 if ((strlen($existingvalue) > 10) && ($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) {
1639 $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value);
1640 break;
1641 }
1642 }
1643
1644 }
1645 if (is_array($value) || empty($ThisFileInfo['comments'][$tagname]) || !in_array(trim($value), $ThisFileInfo['comments'][$tagname])) {
1646 $value = (is_string($value) ? trim($value) : $value);
1647 if (!is_int($key) && !ctype_digit($key)) {
1648 $ThisFileInfo['comments'][$tagname][$key] = $value;
1649 } else {
1650 if (!isset($ThisFileInfo['comments'][$tagname])) {
1651 $ThisFileInfo['comments'][$tagname] = array($value);
1652 } else {
1653 $ThisFileInfo['comments'][$tagname][] = $value;
1654 }
1655 }
1656 }
1657 }
1658 }
1659 }
1660 }
1661
1662 // attempt to standardize spelling of returned keys
1663 if (!empty($ThisFileInfo['comments'])) {
1664 $StandardizeFieldNames = array(
1665 'tracknumber' => 'track_number',
1666 'track' => 'track_number',
1667 );
1668 foreach ($StandardizeFieldNames as $badkey => $goodkey) {
1669 if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) {
1670 $ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey];
1671 unset($ThisFileInfo['comments'][$badkey]);
1672 }
1673 }
1674 }
1675
1676 if ($option_tags_html) {
1677 // Copy ['comments'] to ['comments_html']
1678 if (!empty($ThisFileInfo['comments'])) {
1679 foreach ($ThisFileInfo['comments'] as $field => $values) {
1680 if ($field == 'picture') {
1681 // pictures can take up a lot of space, and we don't need multiple copies of them
1682 // let there be a single copy in [comments][picture], and not elsewhere
1683 continue;
1684 }
1685 foreach ($values as $index => $value) {
1686 if (is_array($value)) {
1687 $ThisFileInfo['comments_html'][$field][$index] = $value;
1688 } else {
1689 $ThisFileInfo['comments_html'][$field][$index] = str_replace('&#0;', '', self::MultiByteCharString2HTML($value, $ThisFileInfo['encoding']));
1690 }
1691 }
1692 }
1693 }
1694 }
1695
1696 }
1697 return true;
1698 }
1699
1700 /**
1701 * @param string $key
1702 * @param int $begin
1703 * @param int $end
1704 * @param string $file
1705 * @param string $name
1706 *
1707 * @return string
1708 */
1709 public static function EmbeddedLookup($key, $begin, $end, $file, $name) {
1710
1711 // Cached
1712 static $cache;
1713 if (isset($cache[$file][$name])) {
1714 return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
1715 }
1716
1717 // Init
1718 $keylength = strlen($key);
1719 $line_count = $end - $begin - 7;
1720
1721 // Open php file
1722 $fp = fopen($file, 'r');
1723
1724 // Discard $begin lines
1725 for ($i = 0; $i < ($begin + 3); $i++) {
1726 fgets($fp, 1024);
1727 }
1728
1729 // Loop thru line
1730 while (0 < $line_count--) {
1731
1732 // Read line
1733 $line = ltrim(fgets($fp, 1024), "\t ");
1734
1735 // METHOD A: only cache the matching key - less memory but slower on next lookup of not-previously-looked-up key
1736 //$keycheck = substr($line, 0, $keylength);
1737 //if ($key == $keycheck) {
1738 // $cache[$file][$name][$keycheck] = substr($line, $keylength + 1);
1739 // break;
1740 //}
1741
1742 // METHOD B: cache all keys in this lookup - more memory but faster on next lookup of not-previously-looked-up key
1743 //$cache[$file][$name][substr($line, 0, $keylength)] = trim(substr($line, $keylength + 1));
1744 $explodedLine = explode("\t", $line, 2);
1745 $ThisKey = $explodedLine[0];
1746 $ThisValue = (isset($explodedLine[1]) ? $explodedLine[1] : '');
1747 $cache[$file][$name][$ThisKey] = trim($ThisValue);
1748 }
1749
1750 // Close and return
1751 fclose($fp);
1752 return (isset($cache[$file][$name][$key]) ? $cache[$file][$name][$key] : '');
1753 }
1754
1755 /**
1756 * @param string $filename
1757 * @param string $sourcefile
1758 * @param bool $DieOnFailure
1759 *
1760 * @return bool
1761 * @throws Exception
1762 */
1763 public static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) {
1764 global $GETID3_ERRORARRAY;
1765
1766 if (file_exists($filename)) {
1767 if (include_once($filename)) {
1768 return true;
1769 } else {
1770 $diemessage = basename($sourcefile).' depends on '.$filename.', which has errors';
1771 }
1772 } else {
1773 $diemessage = basename($sourcefile).' depends on '.$filename.', which is missing';
1774 }
1775 if ($DieOnFailure) {
1776 throw new Exception($diemessage);
1777 } else {
1778 $GETID3_ERRORARRAY[] = $diemessage;
1779 }
1780 return false;
1781 }
1782
1783 /**
1784 * @param string $string
1785 *
1786 * @return string
1787 */
1788 public static function trimNullByte($string) {
1789 return trim($string, "\x00");
1790 }
1791
1792 /**
1793 * @param string $path
1794 *
1795 * @return float|bool
1796 */
1797 public static function getFileSizeSyscall($path) {
1798 $commandline = null;
1799 $filesize = false;
1800
1801 if (GETID3_OS_ISWINDOWS) {
1802 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:
1803 $filesystem = new COM('Scripting.FileSystemObject');
1804 $file = $filesystem->GetFile($path);
1805 $filesize = $file->Size();
1806 unset($filesystem, $file);
1807 } else {
1808 $commandline = 'for %I in ('.escapeshellarg($path).') do @echo %~zI';
1809 }
1810 } else {
1811 $commandline = 'ls -l '.escapeshellarg($path).' | awk \'{print $5}\'';
1812 }
1813 if (isset($commandline)) {
1814 $output = trim(shell_exec($commandline));
1815 if (ctype_digit($output)) {
1816 $filesize = (float) $output;
1817 }
1818 }
1819 return $filesize;
1820 }
1821
1822 /**
1823 * @param string $filename
1824 *
1825 * @return string|false
1826 */
1827 public static function truepath($filename) {
1828 // 2017-11-08: this could use some improvement, patches welcome
1829 if (preg_match('#^(\\\\\\\\|//)[a-z0-9]#i', $filename, $matches)) {
1830 // PHP's built-in realpath function does not work on UNC Windows shares
1831 $goodpath = array();
1832 foreach (explode('/', str_replace('\\', '/', $filename)) as $part) {
1833 if ($part == '.') {
1834 continue;
1835 }
1836 if ($part == '..') {
1837 if (count($goodpath)) {
1838 array_pop($goodpath);
1839 } else {
1840 // cannot step above this level, already at top level
1841 return false;
1842 }
1843 } else {
1844 $goodpath[] = $part;
1845 }
1846 }
1847 return implode(DIRECTORY_SEPARATOR, $goodpath);
1848 }
1849 return realpath($filename);
1850 }
1851
1852 /**
1853 * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268)
1854 *
1855 * @param string $path A path.
1856 * @param string $suffix If the name component ends in suffix this will also be cut off.
1857 *
1858 * @return string
1859 */
1860 public static function mb_basename($path, $suffix = '') {
1861 $splited = preg_split('#/#', rtrim($path, '/ '));
1862 return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1);
1863 }
1864
1865}
1866
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1