Changeset 46112
- Timestamp:
- 09/14/2019 07:06:09 PM (5 years ago)
- Location:
- trunk/src/wp-includes/ID3
- Files:
-
- 18 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/ID3/getid3.lib.php
r41196 r46112 1 1 <?php 2 2 3 ///////////////////////////////////////////////////////////////// 3 4 /// getID3() by James Heinrich <info@getid3.org> // 4 // available at http://getid3.sourceforge.net // 5 // or http://www.getid3.org // 6 // also https://github.com/JamesHeinrich/getID3 // 7 ///////////////////////////////////////////////////////////////// 5 // available at https://github.com/JamesHeinrich/getID3 // 6 // or https://www.getid3.org // 7 // or http://getid3.sourceforge.net // 8 8 // // 9 9 // getid3.lib.php - part of getID3() // 10 // See readme.txt for more details//10 // see readme.txt for more details // 11 11 // /// 12 12 ///////////////////////////////////////////////////////////////// … … 15 15 class getid3_lib 16 16 { 17 17 /** 18 * @param string $string 19 * @param bool $hex 20 * @param bool $spaces 21 * @param string $htmlencoding 22 * 23 * @return string 24 */ 18 25 public static function PrintHexBytes($string, $hex=true, $spaces=true, $htmlencoding='UTF-8') { 19 26 $returnstring = ''; 20 27 for ($i = 0; $i < strlen($string); $i++) { 21 28 if ($hex) { 22 $returnstring .= str_pad(dechex(ord($string {$i})), 2, '0', STR_PAD_LEFT);29 $returnstring .= str_pad(dechex(ord($string[$i])), 2, '0', STR_PAD_LEFT); 23 30 } else { 24 $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string {$i}) ? $string{$i}: '¤');31 $returnstring .= ' '.(preg_match("#[\x20-\x7E]#", $string[$i]) ? $string[$i] : '¤'); 25 32 } 26 33 if ($spaces) { … … 37 44 } 38 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 */ 39 53 public static function trunc($floatnumber) { 40 // truncates a floating-point number at the decimal point41 // returns int (if possible, otherwise float)42 54 if ($floatnumber >= 1) { 43 55 $truncatednumber = floor($floatnumber); … … 53 65 } 54 66 55 67 /** 68 * @param int|null $variable 69 * @param int $increment 70 * 71 * @return bool 72 */ 56 73 public static function safe_inc(&$variable, $increment=1) { 57 74 if (isset($variable)) { … … 63 80 } 64 81 82 /** 83 * @param int|float $floatnum 84 * 85 * @return int|float 86 */ 65 87 public static function CastAsInt($floatnum) { 66 88 // convert to float if not already … … 78 100 } 79 101 102 /** 103 * @param int $num 104 * 105 * @return bool 106 */ 80 107 public static function intValueSupported($num) { 81 108 // check if integers are 64-bit … … 94 121 } 95 122 123 /** 124 * @param string $fraction 125 * 126 * @return float 127 */ 96 128 public static function DecimalizeFraction($fraction) { 97 129 list($numerator, $denominator) = explode('/', $fraction); … … 99 131 } 100 132 101 133 /** 134 * @param string $binarynumerator 135 * 136 * @return float 137 */ 102 138 public static function DecimalBinary2Float($binarynumerator) { 103 139 $numerator = self::Bin2Dec($binarynumerator); … … 106 142 } 107 143 108 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 */ 109 152 public static function NormalizeBinaryPoint($binarypointnumber, $maxbits=52) { 110 // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html111 153 if (strpos($binarypointnumber, '.') === false) { 112 154 $binarypointnumber = '0.'.$binarypointnumber; 113 } elseif ($binarypointnumber {0}== '.') {155 } elseif ($binarypointnumber[0] == '.') { 114 156 $binarypointnumber = '0'.$binarypointnumber; 115 157 } 116 158 $exponent = 0; 117 while (($binarypointnumber {0}!= '1') || (substr($binarypointnumber, 1, 1) != '.')) {159 while (($binarypointnumber[0] != '1') || (substr($binarypointnumber, 1, 1) != '.')) { 118 160 if (substr($binarypointnumber, 1, 1) == '.') { 119 161 $exponent--; … … 123 165 $exponent += ($pointpos - 1); 124 166 $binarypointnumber = str_replace('.', '', $binarypointnumber); 125 $binarypointnumber = $binarypointnumber {0}.'.'.substr($binarypointnumber, 1);167 $binarypointnumber = $binarypointnumber[0].'.'.substr($binarypointnumber, 1); 126 168 } 127 169 } … … 130 172 } 131 173 132 174 /** 175 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html 176 * 177 * @param float $floatvalue 178 * 179 * @return string 180 */ 133 181 public static function Float2BinaryDecimal($floatvalue) { 134 // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/binary.html135 182 $maxbits = 128; // to how many bits of precision should the calculations be taken? 136 183 $intpart = self::trunc($floatvalue); … … 146 193 } 147 194 148 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 */ 149 203 public static function Float2String($floatvalue, $bits) { 150 // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee-expl.html 204 $exponentbits = 0; 205 $fractionbits = 0; 151 206 switch ($bits) { 152 207 case 32: … … 177 232 } 178 233 179 234 /** 235 * @param string $byteword 236 * 237 * @return float|false 238 */ 180 239 public static function LittleEndian2Float($byteword) { 181 240 return self::BigEndian2Float(strrev($byteword)); 182 241 } 183 242 184 243 /** 244 * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic 245 * 246 * @link http://www.psc.edu/general/software/packages/ieee/ieee.html 247 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html 248 * 249 * @param string $byteword 250 * 251 * @return float|false 252 */ 185 253 public static function BigEndian2Float($byteword) { 186 // ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic187 // http://www.psc.edu/general/software/packages/ieee/ieee.html188 // http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html189 190 254 $bitword = self::BigEndian2Bin($byteword); 191 255 if (!$bitword) { 192 256 return 0; 193 257 } 194 $signbit = $bitword{0}; 258 $signbit = $bitword[0]; 259 $floatvalue = 0; 260 $exponentbits = 0; 261 $fractionbits = 0; 195 262 196 263 switch (strlen($byteword) * 8) { … … 209 276 // http://www.mactech.com/articles/mactech/Vol.06/06.01/SANENormalized/ 210 277 $exponentstring = substr($bitword, 1, 15); 211 $isnormalized = intval($bitword {16});278 $isnormalized = intval($bitword[16]); 212 279 $fractionstring = substr($bitword, 17, 63); 213 280 $exponent = pow(2, self::Bin2Dec($exponentstring) - 16383); … … 260 327 } 261 328 262 329 /** 330 * @param string $byteword 331 * @param bool $synchsafe 332 * @param bool $signed 333 * 334 * @return int|float|false 335 * @throws Exception 336 */ 263 337 public static function BigEndian2Int($byteword, $synchsafe=false, $signed=false) { 264 338 $intvalue = 0; … … 270 344 if ($synchsafe) { // disregard MSB, effectively 7-bit bytes 271 345 //$intvalue = $intvalue | (ord($byteword{$i}) & 0x7F) << (($bytewordlen - 1 - $i) * 7); // faster, but runs into problems past 2^31 on 32-bit systems 272 $intvalue += (ord($byteword {$i}) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7);346 $intvalue += (ord($byteword[$i]) & 0x7F) * pow(2, ($bytewordlen - 1 - $i) * 7); 273 347 } else { 274 $intvalue += ord($byteword {$i}) * pow(256, ($bytewordlen - 1 - $i));348 $intvalue += ord($byteword[$i]) * pow(256, ($bytewordlen - 1 - $i)); 275 349 } 276 350 } … … 289 363 } 290 364 291 365 /** 366 * @param string $byteword 367 * @param bool $signed 368 * 369 * @return int|float|false 370 */ 292 371 public static function LittleEndian2Int($byteword, $signed=false) { 293 372 return self::BigEndian2Int(strrev($byteword), false, $signed); 294 373 } 295 374 375 /** 376 * @param string $byteword 377 * 378 * @return string 379 */ 296 380 public static function LittleEndian2Bin($byteword) { 297 381 return self::BigEndian2Bin(strrev($byteword)); 298 382 } 299 383 384 /** 385 * @param string $byteword 386 * 387 * @return string 388 */ 300 389 public static function BigEndian2Bin($byteword) { 301 390 $binvalue = ''; 302 391 $bytewordlen = strlen($byteword); 303 392 for ($i = 0; $i < $bytewordlen; $i++) { 304 $binvalue .= str_pad(decbin(ord($byteword {$i})), 8, '0', STR_PAD_LEFT);393 $binvalue .= str_pad(decbin(ord($byteword[$i])), 8, '0', STR_PAD_LEFT); 305 394 } 306 395 return $binvalue; 307 396 } 308 397 309 398 /** 399 * @param int $number 400 * @param int $minbytes 401 * @param bool $synchsafe 402 * @param bool $signed 403 * 404 * @return string 405 * @throws Exception 406 */ 310 407 public static function BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false) { 311 408 if ($number < 0) { … … 328 425 } 329 426 330 427 /** 428 * @param int $number 429 * 430 * @return string 431 */ 331 432 public static function Dec2Bin($number) { 332 433 while ($number >= 256) { … … 342 443 } 343 444 344 445 /** 446 * @param string $binstring 447 * @param bool $signed 448 * 449 * @return int|float 450 */ 345 451 public static function Bin2Dec($binstring, $signed=false) { 346 452 $signmult = 1; 347 453 if ($signed) { 348 if ($binstring {0}== '1') {454 if ($binstring[0] == '1') { 349 455 $signmult = -1; 350 456 } … … 358 464 } 359 465 360 466 /** 467 * @param string $binstring 468 * 469 * @return string 470 */ 361 471 public static function Bin2String($binstring) { 362 472 // return 'hi' for input of '0110100001101001' … … 369 479 } 370 480 371 481 /** 482 * @param int $number 483 * @param int $minbytes 484 * @param bool $synchsafe 485 * 486 * @return string 487 */ 372 488 public static function LittleEndian2String($number, $minbytes=1, $synchsafe=false) { 373 489 $intstring = ''; … … 384 500 } 385 501 386 502 /** 503 * @param array $array1 504 * @param array $array2 505 * 506 * @return array|false 507 */ 387 508 public static function array_merge_clobber($array1, $array2) { 388 509 // written by kcØhireability*com … … 402 523 } 403 524 404 525 /** 526 * @param array $array1 527 * @param array $array2 528 * 529 * @return array|false 530 */ 405 531 public static function array_merge_noclobber($array1, $array2) { 406 532 if (!is_array($array1) || !is_array($array2)) { … … 418 544 } 419 545 546 /** 547 * @param array $array1 548 * @param array $array2 549 * 550 * @return array|false|null 551 */ 420 552 public static function flipped_array_merge_noclobber($array1, $array2) { 421 553 if (!is_array($array1) || !is_array($array2)) { … … 432 564 } 433 565 434 566 /** 567 * @param array $theArray 568 * 569 * @return bool 570 */ 435 571 public static function ksort_recursive(&$theArray) { 436 572 ksort($theArray); … … 443 579 } 444 580 581 /** 582 * @param string $filename 583 * @param int $numextensions 584 * 585 * @return string 586 */ 445 587 public static function fileextension($filename, $numextensions=1) { 446 588 if (strstr($filename, '.')) { … … 458 600 } 459 601 460 602 /** 603 * @param int $seconds 604 * 605 * @return string 606 */ 461 607 public static function PlaytimeString($seconds) { 462 608 $sign = (($seconds < 0) ? '-' : ''); … … 468 614 } 469 615 470 616 /** 617 * @param int $macdate 618 * 619 * @return int|float 620 */ 471 621 public static function DateMac2Unix($macdate) { 472 622 // Macintosh timestamp: seconds since 00:00h January 1, 1904 … … 475 625 } 476 626 477 627 /** 628 * @param string $rawdata 629 * 630 * @return float 631 */ 478 632 public static function FixedPoint8_8($rawdata) { 479 633 return self::BigEndian2Int(substr($rawdata, 0, 1)) + (float) (self::BigEndian2Int(substr($rawdata, 1, 1)) / pow(2, 8)); 480 634 } 481 635 482 636 /** 637 * @param string $rawdata 638 * 639 * @return float 640 */ 483 641 public static function FixedPoint16_16($rawdata) { 484 642 return self::BigEndian2Int(substr($rawdata, 0, 2)) + (float) (self::BigEndian2Int(substr($rawdata, 2, 2)) / pow(2, 16)); 485 643 } 486 644 487 645 /** 646 * @param string $rawdata 647 * 648 * @return float 649 */ 488 650 public static function FixedPoint2_30($rawdata) { 489 651 $binarystring = self::BigEndian2Bin($rawdata); … … 492 654 493 655 656 /** 657 * @param string $ArrayPath 658 * @param string $Separator 659 * @param mixed $Value 660 * 661 * @return array 662 */ 494 663 public static function CreateDeepArray($ArrayPath, $Separator, $Value) { 495 664 // assigns $Value to a nested array path: … … 508 677 } 509 678 679 /** 680 * @param array $arraydata 681 * @param bool $returnkey 682 * 683 * @return int|false 684 */ 510 685 public static function array_max($arraydata, $returnkey=false) { 511 686 $maxvalue = false; … … 522 697 } 523 698 699 /** 700 * @param array $arraydata 701 * @param bool $returnkey 702 * 703 * @return int|false 704 */ 524 705 public static function array_min($arraydata, $returnkey=false) { 525 706 $minvalue = false; … … 536 717 } 537 718 719 /** 720 * @param string $XMLstring 721 * 722 * @return array|false 723 */ 538 724 public static function XML2array($XMLstring) { 539 725 if (function_exists('simplexml_load_string') && function_exists('libxml_disable_entity_loader')) { … … 549 735 } 550 736 737 /** 738 * @param SimpleXMLElement|array $XMLobject 739 * 740 * @return array 741 */ 551 742 public static function SimpleXMLelement2array($XMLobject) { 552 743 if (!is_object($XMLobject) && !is_array($XMLobject)) { 553 744 return $XMLobject; 554 745 } 555 $XMLarray = (is_object($XMLobject) ? get_object_vars($XMLobject) : $XMLobject);746 $XMLarray = $XMLobject instanceof SimpleXMLElement ? get_object_vars($XMLobject) : $XMLobject; 556 747 foreach ($XMLarray as $key => $value) { 557 748 $XMLarray[$key] = self::SimpleXMLelement2array($value); … … 560 751 } 561 752 562 563 // Allan Hansen <ahØartemis*dk> 564 // self::md5_data() - returns md5sum for a file from startuing position to absolute end position 753 /** 754 * Returns checksum for a file from starting position to absolute end position. 755 * 756 * @param string $file 757 * @param int $offset 758 * @param int $end 759 * @param string $algorithm 760 * 761 * @return string|false 762 * @throws getid3_exception 763 */ 565 764 public static function hash_data($file, $offset, $end, $algorithm) { 566 static $tempdir = '';567 765 if (!self::intValueSupported($end)) { 568 766 return false; 569 767 } 570 switch ($algorithm) { 571 case 'md5': 572 $hash_function = 'md5_file'; 573 $unix_call = 'md5sum'; 574 $windows_call = 'md5sum.exe'; 575 $hash_length = 32; 576 break; 577 578 case 'sha1': 579 $hash_function = 'sha1_file'; 580 $unix_call = 'sha1sum'; 581 $windows_call = 'sha1sum.exe'; 582 $hash_length = 40; 583 break; 584 585 default: 586 throw new Exception('Invalid algorithm ('.$algorithm.') in self::hash_data()'); 587 break; 588 } 768 if (!in_array($algorithm, array('md5', 'sha1'))) { 769 throw new getid3_exception('Invalid algorithm ('.$algorithm.') in self::hash_data()'); 770 } 771 589 772 $size = $end - $offset; 590 while (true) { 591 if (GETID3_OS_ISWINDOWS) { 592 593 // It seems that sha1sum.exe for Windows only works on physical files, does not accept piped data 594 // Fall back to create-temp-file method: 595 if ($algorithm == 'sha1') { 596 break; 597 } 598 599 $RequiredFiles = array('cygwin1.dll', 'head.exe', 'tail.exe', $windows_call); 600 foreach ($RequiredFiles as $required_file) { 601 if (!is_readable(GETID3_HELPERAPPSDIR.$required_file)) { 602 // helper apps not available - fall back to old method 603 break 2; 604 } 605 } 606 $commandline = GETID3_HELPERAPPSDIR.'head.exe -c '.$end.' '.escapeshellarg(str_replace('/', DIRECTORY_SEPARATOR, $file)).' | '; 607 $commandline .= GETID3_HELPERAPPSDIR.'tail.exe -c '.$size.' | '; 608 $commandline .= GETID3_HELPERAPPSDIR.$windows_call; 609 610 } else { 611 612 $commandline = 'head -c'.$end.' '.escapeshellarg($file).' | '; 613 $commandline .= 'tail -c'.$size.' | '; 614 $commandline .= $unix_call; 615 616 } 617 if (preg_match('#(1|ON)#i', ini_get('safe_mode'))) { 618 //throw new Exception('PHP running in Safe Mode - backtick operator not available, using slower non-system-call '.$algorithm.' algorithm'); 619 break; 620 } 621 return substr(`$commandline`, 0, $hash_length); 622 } 623 624 if (empty($tempdir)) { 625 // yes this is ugly, feel free to suggest a better way 626 require_once(dirname(__FILE__).'/getid3.php'); 627 $getid3_temp = new getID3(); 628 $tempdir = $getid3_temp->tempdir; 629 unset($getid3_temp); 630 } 631 // try to create a temporary file in the system temp directory - invalid dirname should force to system temp dir 632 if (($data_filename = tempnam($tempdir, 'gI3')) === false) { 633 // can't find anywhere to create a temp file, just fail 634 return false; 635 } 636 637 // Init 638 $result = false; 639 640 // copy parts of file 641 try { 642 self::CopyFileParts($file, $data_filename, $offset, $end - $offset); 643 $result = $hash_function($data_filename); 644 } catch (Exception $e) { 645 throw new Exception('self::CopyFileParts() failed in getid_lib::hash_data(): '.$e->getMessage()); 646 } 647 unlink($data_filename); 648 return $result; 649 } 650 773 774 $fp = fopen($file, 'rb'); 775 fseek($fp, $offset); 776 $ctx = hash_init($algorithm); 777 while ($size > 0) { 778 $buffer = fread($fp, min($size, getID3::FREAD_BUFFER_SIZE)); 779 hash_update($ctx, $buffer); 780 $size -= getID3::FREAD_BUFFER_SIZE; 781 } 782 $hash = hash_final($ctx); 783 fclose($fp); 784 785 return $hash; 786 } 787 788 /** 789 * @param string $filename_source 790 * @param string $filename_dest 791 * @param int $offset 792 * @param int $length 793 * 794 * @return bool 795 * @throws Exception 796 * 797 * @deprecated Unused, may be removed in future versions of getID3 798 */ 651 799 public static function CopyFileParts($filename_source, $filename_dest, $offset, $length) { 652 800 if (!self::intValueSupported($offset + $length)) { … … 661 809 $byteslefttowrite -= $byteswritten; 662 810 } 811 fclose($fp_dest); 663 812 return true; 664 813 } else { 814 fclose($fp_src); 665 815 throw new Exception('failed to seek to offset '.$offset.' in '.$filename_source); 666 816 } 667 fclose($fp_dest);668 817 } else { 669 818 throw new Exception('failed to create file for writing '.$filename_dest); 670 819 } 671 fclose($fp_src);672 820 } else { 673 821 throw new Exception('failed to open file for reading '.$filename_source); 674 822 } 675 return false; 676 } 677 823 } 824 825 /** 826 * @param int $charval 827 * 828 * @return string 829 */ 678 830 public static function iconv_fallback_int_utf8($charval) { 679 831 if ($charval < 128) { … … 699 851 } 700 852 701 // ISO-8859-1 => UTF-8 853 /** 854 * ISO-8859-1 => UTF-8 855 * 856 * @param string $string 857 * @param bool $bom 858 * 859 * @return string 860 */ 702 861 public static function iconv_fallback_iso88591_utf8($string, $bom=false) { 703 862 if (function_exists('utf8_encode')) { … … 710 869 } 711 870 for ($i = 0; $i < strlen($string); $i++) { 712 $charval = ord($string {$i});871 $charval = ord($string[$i]); 713 872 $newcharstring .= self::iconv_fallback_int_utf8($charval); 714 873 } … … 716 875 } 717 876 718 // ISO-8859-1 => UTF-16BE 877 /** 878 * ISO-8859-1 => UTF-16BE 879 * 880 * @param string $string 881 * @param bool $bom 882 * 883 * @return string 884 */ 719 885 public static function iconv_fallback_iso88591_utf16be($string, $bom=false) { 720 886 $newcharstring = ''; … … 723 889 } 724 890 for ($i = 0; $i < strlen($string); $i++) { 725 $newcharstring .= "\x00".$string {$i};891 $newcharstring .= "\x00".$string[$i]; 726 892 } 727 893 return $newcharstring; 728 894 } 729 895 730 // ISO-8859-1 => UTF-16LE 896 /** 897 * ISO-8859-1 => UTF-16LE 898 * 899 * @param string $string 900 * @param bool $bom 901 * 902 * @return string 903 */ 731 904 public static function iconv_fallback_iso88591_utf16le($string, $bom=false) { 732 905 $newcharstring = ''; … … 735 908 } 736 909 for ($i = 0; $i < strlen($string); $i++) { 737 $newcharstring .= $string {$i}."\x00";910 $newcharstring .= $string[$i]."\x00"; 738 911 } 739 912 return $newcharstring; 740 913 } 741 914 742 // ISO-8859-1 => UTF-16LE (BOM) 915 /** 916 * ISO-8859-1 => UTF-16LE (BOM) 917 * 918 * @param string $string 919 * 920 * @return string 921 */ 743 922 public static function iconv_fallback_iso88591_utf16($string) { 744 923 return self::iconv_fallback_iso88591_utf16le($string, true); 745 924 } 746 925 747 // UTF-8 => ISO-8859-1 926 /** 927 * UTF-8 => ISO-8859-1 928 * 929 * @param string $string 930 * 931 * @return string 932 */ 748 933 public static function iconv_fallback_utf8_iso88591($string) { 749 934 if (function_exists('utf8_decode')) { … … 755 940 $stringlength = strlen($string); 756 941 while ($offset < $stringlength) { 757 if ((ord($string {$offset}) | 0x07) == 0xF7) {942 if ((ord($string[$offset]) | 0x07) == 0xF7) { 758 943 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb 759 $charval = ((ord($string {($offset + 0)}) & 0x07) << 18) &760 ((ord($string {($offset + 1)}) & 0x3F) << 12) &761 ((ord($string {($offset + 2)}) & 0x3F) << 6) &762 (ord($string {($offset + 3)}) & 0x3F);944 $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) & 945 ((ord($string[($offset + 1)]) & 0x3F) << 12) & 946 ((ord($string[($offset + 2)]) & 0x3F) << 6) & 947 (ord($string[($offset + 3)]) & 0x3F); 763 948 $offset += 4; 764 } elseif ((ord($string {$offset}) | 0x0F) == 0xEF) {949 } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) { 765 950 // 1110bbbb 10bbbbbb 10bbbbbb 766 $charval = ((ord($string {($offset + 0)}) & 0x0F) << 12) &767 ((ord($string {($offset + 1)}) & 0x3F) << 6) &768 (ord($string {($offset + 2)}) & 0x3F);951 $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) & 952 ((ord($string[($offset + 1)]) & 0x3F) << 6) & 953 (ord($string[($offset + 2)]) & 0x3F); 769 954 $offset += 3; 770 } elseif ((ord($string {$offset}) | 0x1F) == 0xDF) {955 } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) { 771 956 // 110bbbbb 10bbbbbb 772 $charval = ((ord($string {($offset + 0)}) & 0x1F) << 6) &773 (ord($string {($offset + 1)}) & 0x3F);957 $charval = ((ord($string[($offset + 0)]) & 0x1F) << 6) & 958 (ord($string[($offset + 1)]) & 0x3F); 774 959 $offset += 2; 775 } elseif ((ord($string {$offset}) | 0x7F) == 0x7F) {960 } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) { 776 961 // 0bbbbbbb 777 $charval = ord($string {$offset});962 $charval = ord($string[$offset]); 778 963 $offset += 1; 779 964 } else { … … 789 974 } 790 975 791 // UTF-8 => UTF-16BE 976 /** 977 * UTF-8 => UTF-16BE 978 * 979 * @param string $string 980 * @param bool $bom 981 * 982 * @return string 983 */ 792 984 public static function iconv_fallback_utf8_utf16be($string, $bom=false) { 793 985 $newcharstring = ''; … … 798 990 $stringlength = strlen($string); 799 991 while ($offset < $stringlength) { 800 if ((ord($string {$offset}) | 0x07) == 0xF7) {992 if ((ord($string[$offset]) | 0x07) == 0xF7) { 801 993 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb 802 $charval = ((ord($string {($offset + 0)}) & 0x07) << 18) &803 ((ord($string {($offset + 1)}) & 0x3F) << 12) &804 ((ord($string {($offset + 2)}) & 0x3F) << 6) &805 (ord($string {($offset + 3)}) & 0x3F);994 $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) & 995 ((ord($string[($offset + 1)]) & 0x3F) << 12) & 996 ((ord($string[($offset + 2)]) & 0x3F) << 6) & 997 (ord($string[($offset + 3)]) & 0x3F); 806 998 $offset += 4; 807 } elseif ((ord($string {$offset}) | 0x0F) == 0xEF) {999 } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) { 808 1000 // 1110bbbb 10bbbbbb 10bbbbbb 809 $charval = ((ord($string {($offset + 0)}) & 0x0F) << 12) &810 ((ord($string {($offset + 1)}) & 0x3F) << 6) &811 (ord($string {($offset + 2)}) & 0x3F);1001 $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) & 1002 ((ord($string[($offset + 1)]) & 0x3F) << 6) & 1003 (ord($string[($offset + 2)]) & 0x3F); 812 1004 $offset += 3; 813 } elseif ((ord($string {$offset}) | 0x1F) == 0xDF) {1005 } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) { 814 1006 // 110bbbbb 10bbbbbb 815 $charval = ((ord($string {($offset + 0)}) & 0x1F) << 6) &816 (ord($string {($offset + 1)}) & 0x3F);1007 $charval = ((ord($string[($offset + 0)]) & 0x1F) << 6) & 1008 (ord($string[($offset + 1)]) & 0x3F); 817 1009 $offset += 2; 818 } elseif ((ord($string {$offset}) | 0x7F) == 0x7F) {1010 } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) { 819 1011 // 0bbbbbbb 820 $charval = ord($string {$offset});1012 $charval = ord($string[$offset]); 821 1013 $offset += 1; 822 1014 } else { … … 832 1024 } 833 1025 834 // UTF-8 => UTF-16LE 1026 /** 1027 * UTF-8 => UTF-16LE 1028 * 1029 * @param string $string 1030 * @param bool $bom 1031 * 1032 * @return string 1033 */ 835 1034 public static function iconv_fallback_utf8_utf16le($string, $bom=false) { 836 1035 $newcharstring = ''; … … 841 1040 $stringlength = strlen($string); 842 1041 while ($offset < $stringlength) { 843 if ((ord($string {$offset}) | 0x07) == 0xF7) {1042 if ((ord($string[$offset]) | 0x07) == 0xF7) { 844 1043 // 11110bbb 10bbbbbb 10bbbbbb 10bbbbbb 845 $charval = ((ord($string {($offset + 0)}) & 0x07) << 18) &846 ((ord($string {($offset + 1)}) & 0x3F) << 12) &847 ((ord($string {($offset + 2)}) & 0x3F) << 6) &848 (ord($string {($offset + 3)}) & 0x3F);1044 $charval = ((ord($string[($offset + 0)]) & 0x07) << 18) & 1045 ((ord($string[($offset + 1)]) & 0x3F) << 12) & 1046 ((ord($string[($offset + 2)]) & 0x3F) << 6) & 1047 (ord($string[($offset + 3)]) & 0x3F); 849 1048 $offset += 4; 850 } elseif ((ord($string {$offset}) | 0x0F) == 0xEF) {1049 } elseif ((ord($string[$offset]) | 0x0F) == 0xEF) { 851 1050 // 1110bbbb 10bbbbbb 10bbbbbb 852 $charval = ((ord($string {($offset + 0)}) & 0x0F) << 12) &853 ((ord($string {($offset + 1)}) & 0x3F) << 6) &854 (ord($string {($offset + 2)}) & 0x3F);1051 $charval = ((ord($string[($offset + 0)]) & 0x0F) << 12) & 1052 ((ord($string[($offset + 1)]) & 0x3F) << 6) & 1053 (ord($string[($offset + 2)]) & 0x3F); 855 1054 $offset += 3; 856 } elseif ((ord($string {$offset}) | 0x1F) == 0xDF) {1055 } elseif ((ord($string[$offset]) | 0x1F) == 0xDF) { 857 1056 // 110bbbbb 10bbbbbb 858 $charval = ((ord($string {($offset + 0)}) & 0x1F) << 6) &859 (ord($string {($offset + 1)}) & 0x3F);1057 $charval = ((ord($string[($offset + 0)]) & 0x1F) << 6) & 1058 (ord($string[($offset + 1)]) & 0x3F); 860 1059 $offset += 2; 861 } elseif ((ord($string {$offset}) | 0x7F) == 0x7F) {1060 } elseif ((ord($string[$offset]) | 0x7F) == 0x7F) { 862 1061 // 0bbbbbbb 863 $charval = ord($string {$offset});1062 $charval = ord($string[$offset]); 864 1063 $offset += 1; 865 1064 } else { … … 875 1074 } 876 1075 877 // UTF-8 => UTF-16LE (BOM) 1076 /** 1077 * UTF-8 => UTF-16LE (BOM) 1078 * 1079 * @param string $string 1080 * 1081 * @return string 1082 */ 878 1083 public static function iconv_fallback_utf8_utf16($string) { 879 1084 return self::iconv_fallback_utf8_utf16le($string, true); 880 1085 } 881 1086 882 // UTF-16BE => UTF-8 1087 /** 1088 * UTF-16BE => UTF-8 1089 * 1090 * @param string $string 1091 * 1092 * @return string 1093 */ 883 1094 public static function iconv_fallback_utf16be_utf8($string) { 884 1095 if (substr($string, 0, 2) == "\xFE\xFF") { … … 894 1105 } 895 1106 896 // UTF-16LE => UTF-8 1107 /** 1108 * UTF-16LE => UTF-8 1109 * 1110 * @param string $string 1111 * 1112 * @return string 1113 */ 897 1114 public static function iconv_fallback_utf16le_utf8($string) { 898 1115 if (substr($string, 0, 2) == "\xFF\xFE") { … … 908 1125 } 909 1126 910 // UTF-16BE => ISO-8859-1 1127 /** 1128 * UTF-16BE => ISO-8859-1 1129 * 1130 * @param string $string 1131 * 1132 * @return string 1133 */ 911 1134 public static function iconv_fallback_utf16be_iso88591($string) { 912 1135 if (substr($string, 0, 2) == "\xFE\xFF") { … … 922 1145 } 923 1146 924 // UTF-16LE => ISO-8859-1 1147 /** 1148 * UTF-16LE => ISO-8859-1 1149 * 1150 * @param string $string 1151 * 1152 * @return string 1153 */ 925 1154 public static function iconv_fallback_utf16le_iso88591($string) { 926 1155 if (substr($string, 0, 2) == "\xFF\xFE") { … … 936 1165 } 937 1166 938 // UTF-16 (BOM) => ISO-8859-1 1167 /** 1168 * UTF-16 (BOM) => ISO-8859-1 1169 * 1170 * @param string $string 1171 * 1172 * @return string 1173 */ 939 1174 public static function iconv_fallback_utf16_iso88591($string) { 940 1175 $bom = substr($string, 0, 2); … … 947 1182 } 948 1183 949 // UTF-16 (BOM) => UTF-8 1184 /** 1185 * UTF-16 (BOM) => UTF-8 1186 * 1187 * @param string $string 1188 * 1189 * @return string 1190 */ 950 1191 public static function iconv_fallback_utf16_utf8($string) { 951 1192 $bom = substr($string, 0, 2); … … 958 1199 } 959 1200 1201 /** 1202 * @param string $in_charset 1203 * @param string $out_charset 1204 * @param string $string 1205 * 1206 * @return string 1207 * @throws Exception 1208 */ 960 1209 public static function iconv_fallback($in_charset, $out_charset, $string) { 961 1210 … … 964 1213 } 965 1214 966 // mb_convert_encoding() avail ble1215 // mb_convert_encoding() available 967 1216 if (function_exists('mb_convert_encoding')) { 1217 if ((strtoupper($in_charset) == 'UTF-16') && (substr($string, 0, 2) != "\xFE\xFF") && (substr($string, 0, 2) != "\xFF\xFE")) { 1218 // if BOM missing, mb_convert_encoding will mishandle the conversion, assume UTF-16BE and prepend appropriate BOM 1219 $string = "\xFF\xFE".$string; 1220 } 1221 if ((strtoupper($in_charset) == 'UTF-16') && (strtoupper($out_charset) == 'UTF-8')) { 1222 if (($string == "\xFF\xFE") || ($string == "\xFE\xFF")) { 1223 // if string consists of only BOM, mb_convert_encoding will return the BOM unmodified 1224 return ''; 1225 } 1226 } 968 1227 if ($converted_string = @mb_convert_encoding($string, $out_charset, $in_charset)) { 969 1228 switch ($out_charset) { … … 975 1234 } 976 1235 return $string; 977 } 978 // iconv() avail ble979 elseif (function_exists('iconv')) {1236 1237 // iconv() available 1238 } elseif (function_exists('iconv')) { 980 1239 if ($converted_string = @iconv($in_charset, $out_charset.'//TRANSLIT', $string)) { 981 1240 switch ($out_charset) { … … 1018 1277 } 1019 1278 1279 /** 1280 * @param mixed $data 1281 * @param string $charset 1282 * 1283 * @return mixed 1284 */ 1020 1285 public static function recursiveMultiByteCharString2HTML($data, $charset='ISO-8859-1') { 1021 1286 if (is_string($data)) { … … 1032 1297 } 1033 1298 1299 /** 1300 * @param string|int|float $string 1301 * @param string $charset 1302 * 1303 * @return string 1304 */ 1034 1305 public static function MultiByteCharString2HTML($string, $charset='ISO-8859-1') { 1035 1306 $string = (string) $string; // in case trying to pass a numeric (float, int) string, would otherwise return an empty string … … 1070 1341 $strlen = strlen($string); 1071 1342 for ($i = 0; $i < $strlen; $i++) { 1072 $char_ord_val = ord($string {$i});1343 $char_ord_val = ord($string[$i]); 1073 1344 $charval = 0; 1074 1345 if ($char_ord_val < 0x80) { … … 1076 1347 } elseif ((($char_ord_val & 0xF0) >> 4) == 0x0F && $i+3 < $strlen) { 1077 1348 $charval = (($char_ord_val & 0x07) << 18); 1078 $charval += ((ord($string {++$i}) & 0x3F) << 12);1079 $charval += ((ord($string {++$i}) & 0x3F) << 6);1080 $charval += (ord($string {++$i}) & 0x3F);1349 $charval += ((ord($string[++$i]) & 0x3F) << 12); 1350 $charval += ((ord($string[++$i]) & 0x3F) << 6); 1351 $charval += (ord($string[++$i]) & 0x3F); 1081 1352 } elseif ((($char_ord_val & 0xE0) >> 5) == 0x07 && $i+2 < $strlen) { 1082 1353 $charval = (($char_ord_val & 0x0F) << 12); 1083 $charval += ((ord($string {++$i}) & 0x3F) << 6);1084 $charval += (ord($string {++$i}) & 0x3F);1354 $charval += ((ord($string[++$i]) & 0x3F) << 6); 1355 $charval += (ord($string[++$i]) & 0x3F); 1085 1356 } elseif ((($char_ord_val & 0xC0) >> 6) == 0x03 && $i+1 < $strlen) { 1086 1357 $charval = (($char_ord_val & 0x1F) << 6); 1087 $charval += (ord($string {++$i}) & 0x3F);1358 $charval += (ord($string[++$i]) & 0x3F); 1088 1359 } 1089 1360 if (($charval >= 32) && ($charval <= 127)) { … … 1124 1395 } 1125 1396 1126 1127 1397 /** 1398 * @param int $namecode 1399 * 1400 * @return string 1401 */ 1128 1402 public static function RGADnameLookup($namecode) { 1129 1403 static $RGADname = array(); … … 1137 1411 } 1138 1412 1139 1413 /** 1414 * @param int $originatorcode 1415 * 1416 * @return string 1417 */ 1140 1418 public static function RGADoriginatorLookup($originatorcode) { 1141 1419 static $RGADoriginator = array(); … … 1150 1428 } 1151 1429 1152 1430 /** 1431 * @param int $rawadjustment 1432 * @param int $signbit 1433 * 1434 * @return float 1435 */ 1153 1436 public static function RGADadjustmentLookup($rawadjustment, $signbit) { 1154 $adjustment = $rawadjustment / 10;1437 $adjustment = (float) $rawadjustment / 10; 1155 1438 if ($signbit == 1) { 1156 1439 $adjustment *= -1; 1157 1440 } 1158 return (float) $adjustment; 1159 } 1160 1161 1441 return $adjustment; 1442 } 1443 1444 /** 1445 * @param int $namecode 1446 * @param int $originatorcode 1447 * @param int $replaygain 1448 * 1449 * @return string 1450 */ 1162 1451 public static function RGADgainString($namecode, $originatorcode, $replaygain) { 1163 1452 if ($replaygain < 0) { … … 1175 1464 } 1176 1465 1466 /** 1467 * @param float $amplitude 1468 * 1469 * @return float 1470 */ 1177 1471 public static function RGADamplitude2dB($amplitude) { 1178 1472 return 20 * log10($amplitude); 1179 1473 } 1180 1474 1181 1475 /** 1476 * @param string $imgData 1477 * @param array $imageinfo 1478 * 1479 * @return array|false 1480 */ 1182 1481 public static function GetDataImageSize($imgData, &$imageinfo=array()) { 1183 1482 static $tempdir = ''; … … 1214 1513 } 1215 1514 1515 /** 1516 * @param string $mime_type 1517 * 1518 * @return string 1519 */ 1216 1520 public static function ImageExtFromMime($mime_type) { 1217 1521 // temporary way, works OK for now, but should be reworked in the future … … 1219 1523 } 1220 1524 1221 public static function ImageTypesLookup($imagetypeid) { 1222 static $ImageTypesLookup = array(); 1223 if (empty($ImageTypesLookup)) { 1224 $ImageTypesLookup[1] = 'gif'; 1225 $ImageTypesLookup[2] = 'jpeg'; 1226 $ImageTypesLookup[3] = 'png'; 1227 $ImageTypesLookup[4] = 'swf'; 1228 $ImageTypesLookup[5] = 'psd'; 1229 $ImageTypesLookup[6] = 'bmp'; 1230 $ImageTypesLookup[7] = 'tiff (little-endian)'; 1231 $ImageTypesLookup[8] = 'tiff (big-endian)'; 1232 $ImageTypesLookup[9] = 'jpc'; 1233 $ImageTypesLookup[10] = 'jp2'; 1234 $ImageTypesLookup[11] = 'jpx'; 1235 $ImageTypesLookup[12] = 'jb2'; 1236 $ImageTypesLookup[13] = 'swc'; 1237 $ImageTypesLookup[14] = 'iff'; 1238 } 1239 return (isset($ImageTypesLookup[$imagetypeid]) ? $ImageTypesLookup[$imagetypeid] : ''); 1240 } 1241 1525 /** 1526 * @param array $ThisFileInfo 1527 * 1528 * @return bool 1529 */ 1242 1530 public static function CopyTagsToComments(&$ThisFileInfo) { 1243 1531 … … 1327 1615 } 1328 1616 1329 1617 /** 1618 * @param string $key 1619 * @param int $begin 1620 * @param int $end 1621 * @param string $file 1622 * @param string $name 1623 * 1624 * @return string 1625 */ 1330 1626 public static function EmbeddedLookup($key, $begin, $end, $file, $name) { 1331 1627 … … 1374 1670 } 1375 1671 1672 /** 1673 * @param string $filename 1674 * @param string $sourcefile 1675 * @param bool $DieOnFailure 1676 * 1677 * @return bool 1678 * @throws Exception 1679 */ 1376 1680 public static function IncludeDependency($filename, $sourcefile, $DieOnFailure=false) { 1377 1681 global $GETID3_ERRORARRAY; … … 1394 1698 } 1395 1699 1700 /** 1701 * @param string $string 1702 * 1703 * @return string 1704 */ 1396 1705 public static function trimNullByte($string) { 1397 1706 return trim($string, "\x00"); 1398 1707 } 1399 1708 1709 /** 1710 * @param string $path 1711 * 1712 * @return float|bool 1713 */ 1400 1714 public static function getFileSizeSyscall($path) { 1401 1715 $filesize = false; … … 1422 1736 } 1423 1737 1424 1425 /** 1426 * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268) 1427 * @param string $path A path. 1428 * @param string $suffix If the name component ends in suffix this will also be cut off. 1429 * @return string 1430 */ 1738 /** 1739 * @param string $filename 1740 * 1741 * @return string|false 1742 */ 1743 public static function truepath($filename) { 1744 // 2017-11-08: this could use some improvement, patches welcome 1745 if (preg_match('#^(\\\\\\\\|//)[a-z0-9]#i', $filename, $matches)) { 1746 // PHP's built-in realpath function does not work on UNC Windows shares 1747 $goodpath = array(); 1748 foreach (explode('/', str_replace('\\', '/', $filename)) as $part) { 1749 if ($part == '.') { 1750 continue; 1751 } 1752 if ($part == '..') { 1753 if (count($goodpath)) { 1754 array_pop($goodpath); 1755 } else { 1756 // cannot step above this level, already at top level 1757 return false; 1758 } 1759 } else { 1760 $goodpath[] = $part; 1761 } 1762 } 1763 return implode(DIRECTORY_SEPARATOR, $goodpath); 1764 } 1765 return realpath($filename); 1766 } 1767 1768 /** 1769 * Workaround for Bug #37268 (https://bugs.php.net/bug.php?id=37268) 1770 * 1771 * @param string $path A path. 1772 * @param string $suffix If the name component ends in suffix this will also be cut off. 1773 * 1774 * @return string 1775 */ 1431 1776 public static function mb_basename($path, $suffix = null) { 1432 1777 $splited = preg_split('#/#', rtrim($path, '/ ')); -
trunk/src/wp-includes/ID3/getid3.php
r41196 r46112 2 2 ///////////////////////////////////////////////////////////////// 3 3 /// getID3() by James Heinrich <info@getid3.org> // 4 // available at http://getid3.sourceforge.net // 5 // or http://www.getid3.org // 6 // also https://github.com/JamesHeinrich/getID3 // 7 ///////////////////////////////////////////////////////////////// 4 // available at https://github.com/JamesHeinrich/getID3 // 5 // or https://www.getid3.org // 6 // or http://getid3.sourceforge.net // 8 7 // // 9 8 // Please see readme.txt for more information // … … 26 25 define('ENT_SUBSTITUTE', (defined('ENT_IGNORE') ? ENT_IGNORE : 8)); 27 26 } 27 28 /* 29 https://www.getid3.org/phpBB3/viewtopic.php?t=2114 30 If you are running into a the problem where filenames with special characters are being handled 31 incorrectly by external helper programs (e.g. metaflac), notably with the special characters removed, 32 and you are passing in the filename in UTF8 (typically via a HTML form), try uncommenting this line: 33 */ 34 //setlocale(LC_CTYPE, 'en_US.UTF-8'); 28 35 29 36 // attempt to define temp dir as something flexible but reliable … … 75 82 class getID3 76 83 { 77 // public: Settings 78 public $encoding = 'UTF-8'; // CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE 79 public $encoding_id3v1 = 'ISO-8859-1'; // Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252' 80 81 // public: Optional tag checks - disable for speed. 82 public $option_tag_id3v1 = true; // Read and process ID3v1 tags 83 public $option_tag_id3v2 = true; // Read and process ID3v2 tags 84 public $option_tag_lyrics3 = true; // Read and process Lyrics3 tags 85 public $option_tag_apetag = true; // Read and process APE tags 86 public $option_tags_process = true; // Copy tags to root key 'tags' and encode to $this->encoding 87 public $option_tags_html = true; // Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities 88 89 // public: Optional tag/comment calucations 90 public $option_extra_info = true; // Calculate additional info such as bitrate, channelmode etc 91 92 // public: Optional handling of embedded attachments (e.g. images) 93 public $option_save_attachments = true; // defaults to true (ATTACHMENTS_INLINE) for backward compatibility 94 95 // public: Optional calculations 96 public $option_md5_data = false; // Get MD5 sum of data part - slow 97 public $option_md5_data_source = false; // Use MD5 of source file if availble - only FLAC and OptimFROG 98 public $option_sha1_data = false; // Get SHA1 sum of data part - slow 99 public $option_max_2gb_check = null; // Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on PHP_INT_MAX) 100 101 // public: Read buffer size in bytes 84 /* 85 * Settings 86 */ 87 88 /** 89 * CASE SENSITIVE! - i.e. (must be supported by iconv()). Examples: ISO-8859-1 UTF-8 UTF-16 UTF-16BE 90 * 91 * @var string 92 */ 93 public $encoding = 'UTF-8'; 94 95 /** 96 * Should always be 'ISO-8859-1', but some tags may be written in other encodings such as 'EUC-CN' or 'CP1252' 97 * 98 * @var string 99 */ 100 public $encoding_id3v1 = 'ISO-8859-1'; 101 102 /* 103 * Optional tag checks - disable for speed. 104 */ 105 106 /** 107 * Read and process ID3v1 tags 108 * 109 * @var bool 110 */ 111 public $option_tag_id3v1 = true; 112 113 /** 114 * Read and process ID3v2 tags 115 * 116 * @var bool 117 */ 118 public $option_tag_id3v2 = true; 119 120 /** 121 * Read and process Lyrics3 tags 122 * 123 * @var bool 124 */ 125 public $option_tag_lyrics3 = true; 126 127 /** 128 * Read and process APE tags 129 * 130 * @var bool 131 */ 132 public $option_tag_apetag = true; 133 134 /** 135 * Copy tags to root key 'tags' and encode to $this->encoding 136 * 137 * @var bool 138 */ 139 public $option_tags_process = true; 140 141 /** 142 * Copy tags to root key 'tags_html' properly translated from various encodings to HTML entities 143 * 144 * @var bool 145 */ 146 public $option_tags_html = true; 147 148 /* 149 * Optional tag/comment calculations 150 */ 151 152 /** 153 * Calculate additional info such as bitrate, channelmode etc 154 * 155 * @var bool 156 */ 157 public $option_extra_info = true; 158 159 /* 160 * Optional handling of embedded attachments (e.g. images) 161 */ 162 163 /** 164 * Defaults to true (ATTACHMENTS_INLINE) for backward compatibility 165 * 166 * @var bool|string 167 */ 168 public $option_save_attachments = true; 169 170 /* 171 * Optional calculations 172 */ 173 174 /** 175 * Get MD5 sum of data part - slow 176 * 177 * @var bool 178 */ 179 public $option_md5_data = false; 180 181 /** 182 * Use MD5 of source file if availble - only FLAC and OptimFROG 183 * 184 * @var bool 185 */ 186 public $option_md5_data_source = false; 187 188 /** 189 * Get SHA1 sum of data part - slow 190 * 191 * @var bool 192 */ 193 public $option_sha1_data = false; 194 195 /** 196 * Check whether file is larger than 2GB and thus not supported by 32-bit PHP (null: auto-detect based on 197 * PHP_INT_MAX) 198 * 199 * @var bool|null 200 */ 201 public $option_max_2gb_check; 202 203 /** 204 * Read buffer size in bytes 205 * 206 * @var int 207 */ 102 208 public $option_fread_buffer_size = 32768; 103 209 104 210 // Public variables 105 public $filename; // Filename of file being analysed. 106 public $fp; // Filepointer to file being analysed. 107 public $info; // Result array. 211 212 /** 213 * Filename of file being analysed. 214 * 215 * @var string 216 */ 217 public $filename; 218 219 /** 220 * Filepointer to file being analysed. 221 * 222 * @var resource 223 */ 224 public $fp; 225 226 /** 227 * Result array. 228 * 229 * @var array 230 */ 231 public $info; 232 233 /** 234 * @var string 235 */ 108 236 public $tempdir = GETID3_TEMP_DIR; 237 238 /** 239 * @var int 240 */ 109 241 public $memory_limit = 0; 110 242 111 // Protected variables 243 /** 244 * @var string 245 */ 112 246 protected $startup_error = ''; 247 248 /** 249 * @var string 250 */ 113 251 protected $startup_warning = ''; 114 252 115 const VERSION = '1.9.1 4-201706111222';253 const VERSION = '1.9.17-201907240906'; 116 254 const FREAD_BUFFER_SIZE = 32768; 117 255 … … 119 257 const ATTACHMENTS_INLINE = true; 120 258 121 // public: constructor122 259 public function __construct() { 260 261 // Check for PHP version 262 $required_php_version = '5.3.0'; 263 if (version_compare(PHP_VERSION, $required_php_version, '<')) { 264 $this->startup_error .= 'getID3() requires PHP v'.$required_php_version.' or higher - you are running v'.PHP_VERSION."\n"; 265 return; 266 } 123 267 124 268 // Check memory … … 177 321 // Needed for Windows only: 178 322 // Define locations of helper applications for Shorten, VorbisComment, MetaFLAC 179 // as well as other helper functions such as head, tail, md5sum,etc323 // as well as other helper functions such as head, etc 180 324 // This path cannot contain spaces, but the below code will attempt to get the 181 325 // 8.3-equivalent path automatically … … 220 364 throw new getid3_exception($this->startup_error); 221 365 } 222 223 return true; 224 } 225 366 } 367 368 /** 369 * @return string 370 */ 226 371 public function version() { 227 372 return self::VERSION; 228 373 } 229 374 375 /** 376 * @return int 377 */ 230 378 public function fread_buffer_size() { 231 379 return $this->option_fread_buffer_size; 232 380 } 233 381 234 235 // public: setOption 382 /** 383 * @param array $optArray 384 * 385 * @return bool 386 */ 236 387 public function setOption($optArray) { 237 388 if (!is_array($optArray) || empty($optArray)) { … … 247 398 } 248 399 249 250 public function openfile($filename, $filesize=null) { 400 /** 401 * @param string $filename 402 * @param int $filesize 403 * 404 * @return bool 405 * 406 * @throws getid3_exception 407 */ 408 public function openfile($filename, $filesize=null, $fp=null) { 251 409 try { 252 410 if (!empty($this->startup_error)) { … … 271 429 272 430 $filename = str_replace('/', DIRECTORY_SEPARATOR, $filename); 273 $filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename);431 //$filename = preg_replace('#(?<!gs:)('.preg_quote(DIRECTORY_SEPARATOR).'{2,})#', DIRECTORY_SEPARATOR, $filename); 274 432 275 433 // open local file 276 //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see http://www.getid3.org/phpBB3/viewtopic.php?t=1720 277 if ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { 434 //if (is_readable($filename) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { // see https://www.getid3.org/phpBB3/viewtopic.php?t=1720 435 if (($fp != null) && ((get_resource_type($fp) == 'file') || (get_resource_type($fp) == 'stream'))) { 436 $this->fp = $fp; 437 } elseif ((is_readable($filename) || file_exists($filename)) && is_file($filename) && ($this->fp = fopen($filename, 'rb'))) { 278 438 // great 279 439 } else { … … 332 492 unset($this->info['filesize']); 333 493 fclose($this->fp); 334 throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize , 3).'GB, please report to info@getid3.org');494 throw new getid3_exception('PHP seems to think the file is larger than '.round(PHP_INT_MAX / 1073741824).'GB, but filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB, please report to info@getid3.org'); 335 495 } 336 496 $this->info['filesize'] = $real_filesize; 337 $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize , 3).'GB) and is not properly supported by PHP.');497 $this->warning('File is larger than '.round(PHP_INT_MAX / 1073741824).'GB (filesystem reports it as '.number_format($real_filesize / 1073741824, 3).'GB) and is not properly supported by PHP.'); 338 498 } 339 499 } … … 347 507 } 348 508 349 // public: analyze file 350 public function analyze($filename, $filesize=null, $original_filename='') { 509 /** 510 * analyze file 511 * 512 * @param string $filename 513 * @param int $filesize 514 * @param string $original_filename 515 * 516 * @return array 517 */ 518 public function analyze($filename, $filesize=null, $original_filename='', $fp=null) { 351 519 try { 352 if (!$this->openfile($filename, $filesize )) {520 if (!$this->openfile($filename, $filesize, $fp)) { 353 521 return $this->info; 354 522 } … … 384 552 if ((substr($header, 0, 3) == 'ID3') && (strlen($header) == 10)) { 385 553 $this->info['id3v2']['header'] = true; 386 $this->info['id3v2']['majorversion'] = ord($header {3});387 $this->info['id3v2']['minorversion'] = ord($header {4});554 $this->info['id3v2']['majorversion'] = ord($header[3]); 555 $this->info['id3v2']['minorversion'] = ord($header[4]); 388 556 $this->info['avdataoffset'] += getid3_lib::BigEndian2Int(substr($header, 6, 4), 1) + 10; // length of ID3v2 tag in 10-byte header doesn't include 10-byte header length 389 557 } … … 498 666 499 667 500 // private: error handling 668 /** 669 * Error handling. 670 * 671 * @param string $message 672 * 673 * @return array 674 */ 501 675 public function error($message) { 502 676 $this->CleanUp(); … … 509 683 510 684 511 // private: warning handling 685 /** 686 * Warning handling. 687 * 688 * @param string $message 689 * 690 * @return bool 691 */ 512 692 public function warning($message) { 513 693 $this->info['warning'][] = $message; … … 516 696 517 697 518 // private: CleanUp 698 /** 699 * @return bool 700 */ 519 701 private function CleanUp() { 520 702 … … 563 745 } 564 746 565 566 // return array containing information about all supported formats 747 /** 748 * Return array containing information about all supported formats. 749 * 750 * @return array 751 */ 567 752 public function GetFileFormatArray() { 568 753 static $format_info = array(); … … 585 770 'group' => 'audio', 586 771 'module' => 'aac', 587 'mime_type' => 'a pplication/octet-stream',772 'mime_type' => 'audio/aac', 588 773 'fail_ape' => 'WARNING', 589 774 ), … … 603 788 'group' => 'audio', 604 789 'module' => 'aac', 605 'mime_type' => 'a pplication/octet-stream',790 'mime_type' => 'audio/aac', 606 791 'fail_ape' => 'WARNING', 607 792 ), … … 650 835 // DSS - audio - Digital Speech Standard 651 836 'dss' => array( 652 'pattern' => '^[\\x02-\\x0 6]ds[s2]',837 'pattern' => '^[\\x02-\\x08]ds[s2]', 653 838 'group' => 'audio', 654 839 'module' => 'dss', … … 669 854 'group' => 'audio', 670 855 'module' => 'flac', 671 'mime_type' => 'audio/ x-flac',856 'mime_type' => 'audio/flac', 672 857 ), 673 858 … … 701 886 'group' => 'audio', 702 887 'module' => 'monkey', 703 'mime_type' => 'a pplication/octet-stream',888 'mime_type' => 'audio/x-monkeys-audio', 704 889 ), 705 890 … … 890 1075 'group' => 'audio-video', 891 1076 'module' => 'riff', 892 'mime_type' => 'audio/ x-wav',1077 'mime_type' => 'audio/wav', 893 1078 'fail_ape' => 'WARNING', 894 1079 ), … … 1054 1239 'group' => 'archive', 1055 1240 'module' => 'gzip', 1056 'mime_type' => 'application/ x-gzip',1241 'mime_type' => 'application/gzip', 1057 1242 'fail_id3' => 'ERROR', 1058 1243 'fail_ape' => 'ERROR', … … 1069 1254 ), 1070 1255 1256 // XZ - data - XZ compressed data 1257 'xz' => array( 1258 'pattern' => '^\\xFD7zXZ\\x00', 1259 'group' => 'archive', 1260 'module' => 'xz', 1261 'mime_type' => 'application/x-xz', 1262 'fail_id3' => 'ERROR', 1263 'fail_ape' => 'ERROR', 1264 ), 1265 1071 1266 1072 1267 // Misc other formats … … 1116 1311 } 1117 1312 1118 1119 1313 /** 1314 * @param string $filedata 1315 * @param string $filename 1316 * 1317 * @return mixed|false 1318 */ 1120 1319 public function GetFileFormat(&$filedata, $filename='') { 1121 1320 // this function will determine the format of a file based on usually … … 1136 1335 1137 1336 if (preg_match('#\\.mp[123a]$#i', $filename)) { 1138 // Too many mp3 encoders on the market put ga bage in front of mpeg files1337 // Too many mp3 encoders on the market put garbage in front of mpeg files 1139 1338 // use assume format on these if format detection failed 1140 1339 $GetFileFormatArray = $this->GetFileFormatArray(); … … 1155 1354 } 1156 1355 1157 1158 // converts array to $encoding charset from $this->encoding 1356 /** 1357 * Converts array to $encoding charset from $this->encoding. 1358 * 1359 * @param array $array 1360 * @param string $encoding 1361 */ 1159 1362 public function CharConvert(&$array, $encoding) { 1160 1363 … … 1179 1382 } 1180 1383 1181 1384 /** 1385 * @return bool 1386 */ 1182 1387 public function HandleAllTags() { 1183 1388 … … 1234 1439 } 1235 1440 if ($tag_key == 'picture') { 1441 // pictures can take up a lot of space, and we don't need multiple copies of them; let there be a single copy in [comments][picture], and not elsewhere 1236 1442 unset($this->info[$comment_name]['comments'][$tag_key]); 1237 1443 } … … 1247 1453 if ($this->option_tags_html) { 1248 1454 foreach ($this->info['tags'][$tag_name] as $tag_key => $valuearray) { 1455 if ($tag_key == 'picture') { 1456 // Do not to try to convert binary picture data to HTML 1457 // https://github.com/JamesHeinrich/getID3/issues/178 1458 continue; 1459 } 1249 1460 $this->info['tags_html'][$tag_name][$tag_key] = getid3_lib::recursiveMultiByteCharString2HTML($valuearray, $this->info[$comment_name]['encoding']); 1250 1461 } … … 1255 1466 } 1256 1467 1257 // pictures can take up a lot of space, and we don't need multiple copies of them 1258 // let there be a single copy in [comments][picture], and not elsewhere 1468 // pictures can take up a lot of space, and we don't need multiple copies of them; let there be a single copy in [comments][picture], and not elsewhere 1259 1469 if (!empty($this->info['tags'])) { 1260 1470 $unset_keys = array('tags', 'tags_html'); … … 1302 1512 } 1303 1513 1514 /** 1515 * @param string $algorithm 1516 * 1517 * @return array|bool 1518 */ 1304 1519 public function getHashdata($algorithm) { 1305 1520 switch ($algorithm) { … … 1366 1581 } else { 1367 1582 1368 $commandline = 'vorbiscomment -w -c "'.$empty.'" "'.$file.'" "'.$temp.'" 2>&1';1369 1583 $commandline = 'vorbiscomment -w -c '.escapeshellarg($empty).' '.escapeshellarg($file).' '.escapeshellarg($temp).' 2>&1'; 1370 1584 $VorbisCommentError = `$commandline`; … … 1424 1638 return true; 1425 1639 } 1426 1427 1640 1428 1641 public function ChannelsBitratePlaytimeCalculations() { … … 1490 1703 } 1491 1704 1492 1705 /** 1706 * @return bool 1707 */ 1493 1708 public function CalculateCompressionRatioVideo() { 1494 1709 if (empty($this->info['video'])) { … … 1538 1753 } 1539 1754 1540 1755 /** 1756 * @return bool 1757 */ 1541 1758 public function CalculateCompressionRatioAudio() { 1542 1759 if (empty($this->info['audio']['bitrate']) || empty($this->info['audio']['channels']) || empty($this->info['audio']['sample_rate']) || !is_numeric($this->info['audio']['sample_rate'])) { … … 1555 1772 } 1556 1773 1557 1774 /** 1775 * @return bool 1776 */ 1558 1777 public function CalculateReplayGain() { 1559 1778 if (isset($this->info['replay_gain'])) { 1560 1779 if (!isset($this->info['replay_gain']['reference_volume'])) { 1561 $this->info['replay_gain']['reference_volume'] = (double)89.0;1780 $this->info['replay_gain']['reference_volume'] = 89.0; 1562 1781 } 1563 1782 if (isset($this->info['replay_gain']['track']['adjustment'])) { … … 1578 1797 } 1579 1798 1799 /** 1800 * @return bool 1801 */ 1580 1802 public function ProcessAudioStreams() { 1581 1803 if (!empty($this->info['audio']['bitrate']) || !empty($this->info['audio']['channels']) || !empty($this->info['audio']['sample_rate'])) { … … 1591 1813 } 1592 1814 1815 /** 1816 * @return string|bool 1817 */ 1593 1818 public function getid3_tempnam() { 1594 1819 return tempnam($this->tempdir, 'gI3'); 1595 1820 } 1596 1821 1822 /** 1823 * @param string $name 1824 * 1825 * @return bool 1826 * 1827 * @throws getid3_exception 1828 */ 1597 1829 public function include_module($name) { 1598 1830 //if (!file_exists($this->include_path.'module.'.$name.'.php')) { … … 1604 1836 } 1605 1837 1606 public static function is_writable ($filename) { 1607 $ret = is_writable($filename); 1608 1609 if (!$ret) { 1610 $perms = fileperms($filename); 1611 $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002); 1612 } 1613 1614 return $ret; 1615 } 1838 /** 1839 * @param string $filename 1840 * 1841 * @return bool 1842 */ 1843 public static function is_writable ($filename) { 1844 $ret = is_writable($filename); 1845 if (!$ret) { 1846 $perms = fileperms($filename); 1847 $ret = ($perms & 0x0080) || ($perms & 0x0010) || ($perms & 0x0002); 1848 } 1849 return $ret; 1850 } 1616 1851 1617 1852 } 1618 1853 1619 1854 1620 abstract class getid3_handler { 1855 abstract class getid3_handler 1856 { 1621 1857 1622 1858 /** … … 1625 1861 protected $getid3; // pointer 1626 1862 1627 protected $data_string_flag = false; // analyzing filepointer or string 1628 protected $data_string = ''; // string to analyze 1629 protected $data_string_position = 0; // seek position in string 1630 protected $data_string_length = 0; // string length 1631 1632 private $dependency_to = null; 1633 1634 1863 /** 1864 * Analyzing filepointer or string. 1865 * 1866 * @var bool 1867 */ 1868 protected $data_string_flag = false; 1869 1870 /** 1871 * String to analyze. 1872 * 1873 * @var string 1874 */ 1875 protected $data_string = ''; 1876 1877 /** 1878 * Seek position in string. 1879 * 1880 * @var int 1881 */ 1882 protected $data_string_position = 0; 1883 1884 /** 1885 * String length. 1886 * 1887 * @var int 1888 */ 1889 protected $data_string_length = 0; 1890 1891 /** 1892 * @var string 1893 */ 1894 private $dependency_to; 1895 1896 /** 1897 * getid3_handler constructor. 1898 * 1899 * @param getID3 $getid3 1900 * @param string $call_module 1901 */ 1635 1902 public function __construct(getID3 $getid3, $call_module=null) { 1636 1903 $this->getid3 = $getid3; … … 1641 1908 } 1642 1909 1643 1644 // Analyze from file pointer 1910 /** 1911 * Analyze from file pointer. 1912 * 1913 * @return bool 1914 */ 1645 1915 abstract public function Analyze(); 1646 1916 1647 1648 // Analyze from string instead 1917 /** 1918 * Analyze from string instead. 1919 * 1920 * @param string $string 1921 */ 1649 1922 public function AnalyzeString($string) { 1650 1923 // Enter string mode … … 1672 1945 } 1673 1946 1947 /** 1948 * @param string $string 1949 */ 1674 1950 public function setStringMode($string) { 1675 1951 $this->data_string_flag = true; … … 1678 1954 } 1679 1955 1956 /** 1957 * @return int|bool 1958 */ 1680 1959 protected function ftell() { 1681 1960 if ($this->data_string_flag) { … … 1685 1964 } 1686 1965 1966 /** 1967 * @param int $bytes 1968 * 1969 * @return string|false 1970 * 1971 * @throws getid3_exception 1972 */ 1687 1973 protected function fread($bytes) { 1688 1974 if ($this->data_string_flag) { … … 1697 1983 //return fread($this->getid3->fp, $bytes); 1698 1984 /* 1699 * http ://www.getid3.org/phpBB3/viewtopic.php?t=19301985 * https://www.getid3.org/phpBB3/viewtopic.php?t=1930 1700 1986 * "I found out that the root cause for the problem was how getID3 uses the PHP system function fread(). 1701 1987 * It seems to assume that fread() would always return as many bytes as were requested. … … 1705 1991 $contents = ''; 1706 1992 do { 1993 //if (($this->getid3->memory_limit > 0) && ($bytes > $this->getid3->memory_limit)) { 1994 if (($this->getid3->memory_limit > 0) && (($bytes / $this->getid3->memory_limit) > 0.99)) { // enable a more-fuzzy match to prevent close misses generating errors like "PHP Fatal error: Allowed memory size of 33554432 bytes exhausted (tried to allocate 33554464 bytes)" 1995 throw new getid3_exception('cannot fread('.$bytes.' from '.$this->ftell().') that is more than available PHP memory ('.$this->getid3->memory_limit.')', 10); 1996 } 1707 1997 $part = fread($this->getid3->fp, $bytes); 1708 1998 $partLength = strlen($part); … … 1713 2003 } 1714 2004 2005 /** 2006 * @param int $bytes 2007 * @param int $whence 2008 * 2009 * @return int 2010 * 2011 * @throws getid3_exception 2012 */ 1715 2013 protected function fseek($bytes, $whence=SEEK_SET) { 1716 2014 if ($this->data_string_flag) { … … 1743 2041 } 1744 2042 2043 /** 2044 * @return bool 2045 */ 1745 2046 protected function feof() { 1746 2047 if ($this->data_string_flag) { … … 1750 2051 } 1751 2052 2053 /** 2054 * @param string $module 2055 * 2056 * @return bool 2057 */ 1752 2058 final protected function isDependencyFor($module) { 1753 2059 return $this->dependency_to == $module; 1754 2060 } 1755 2061 2062 /** 2063 * @param string $text 2064 * 2065 * @return bool 2066 */ 1756 2067 protected function error($text) { 1757 2068 $this->getid3->info['error'][] = $text; … … 1760 2071 } 1761 2072 2073 /** 2074 * @param string $text 2075 * 2076 * @return bool 2077 */ 1762 2078 protected function warning($text) { 1763 2079 return $this->getid3->warning($text); 1764 2080 } 1765 2081 2082 /** 2083 * @param string $text 2084 */ 1766 2085 protected function notice($text) { 1767 2086 // does nothing for now 1768 2087 } 1769 2088 2089 /** 2090 * @param string $name 2091 * @param int $offset 2092 * @param int $length 2093 * @param string $image_mime 2094 * 2095 * @return string|null 2096 * 2097 * @throws Exception 2098 * @throws getid3_exception 2099 */ 1770 2100 public function saveAttachment($name, $offset, $length, $image_mime=null) { 1771 2101 try { … … 1821 2151 if (isset($fp_dest) && is_resource($fp_dest)) { 1822 2152 fclose($fp_dest); 2153 } 2154 2155 if (isset($dest) && file_exists($dest)) { 1823 2156 unlink($dest); 1824 2157 } -
trunk/src/wp-includes/ID3/license.txt
r32979 r46112 2 2 /// getID3() by James Heinrich <info@getid3.org> // 3 3 // available at http://getid3.sourceforge.net // 4 // or http ://www.getid3.org//4 // or https://www.getid3.org // 5 5 // also https://github.com/JamesHeinrich/getID3 // 6 6 ///////////////////////////////////////////////////////////////// … … 19 19 GNU LGPL: https://gnu.org/licenses/lgpl.html (v3) 20 20 21 Mozilla MPL: http ://www.mozilla.org/MPL/2.0/(v2)21 Mozilla MPL: https://www.mozilla.org/MPL/2.0/ (v2) 22 22 23 getID3 Commercial License: http ://getid3.org/#gCL (payment required)23 getID3 Commercial License: https://www.getid3.org/#gCL (payment required) 24 24 25 25 ***************************************************************** -
trunk/src/wp-includes/ID3/module.audio-video.asf.php
r41196 r46112 2 2 ///////////////////////////////////////////////////////////////// 3 3 /// getID3() by James Heinrich <info@getid3.org> // 4 // available at http://getid3.sourceforge.net // 5 // or http://www.getid3.org // 6 // also https://github.com/JamesHeinrich/getID3 // 7 ///////////////////////////////////////////////////////////////// 8 // See readme.txt for more details // 4 // available at https://github.com/JamesHeinrich/getID3 // 5 // or https://www.getid3.org // 6 // or http://getid3.sourceforge.net // 7 // see readme.txt for more details // 9 8 ///////////////////////////////////////////////////////////////// 10 9 // // … … 17 16 getid3_lib::IncludeDependency(GETID3_INCLUDEPATH.'module.audio-video.riff.php', __FILE__, true); 18 17 19 class getid3_asf extends getid3_handler { 20 18 class getid3_asf extends getid3_handler 19 { 20 /** 21 * @param getID3 $getid3 22 */ 21 23 public function __construct(getID3 $getid3) { 22 24 parent::__construct($getid3); // extends getid3_handler::__construct() … … 31 33 } 32 34 35 /** 36 * @return bool 37 */ 33 38 public function Analyze() { 34 39 $info = &$this->getid3->info; … … 84 89 $ASFHeaderData = $this->fread($thisfile_asf_headerobject['objectsize'] - 30); 85 90 $offset = 0; 91 $thisfile_asf_streambitratepropertiesobject = array(); 92 $thisfile_asf_codeclistobject = array(); 86 93 87 94 for ($HeaderObjectsCounter = 0; $HeaderObjectsCounter < $thisfile_asf_headerobject['headerobjects']; $HeaderObjectsCounter++) { … … 791 798 case 'tracknumber': 792 799 // be careful casting to int: casting unicode strings to int gives unexpected results (stops parsing at first non-numeric character) 793 $thisfile_asf_comments['track '] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));794 foreach ($thisfile_asf_comments['track '] as $key => $value) {800 $thisfile_asf_comments['track_number'] = array($this->TrimTerm($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); 801 foreach ($thisfile_asf_comments['track_number'] as $key => $value) { 795 802 if (preg_match('/^[0-9\x00]+$/', $value)) { 796 $thisfile_asf_comments['track '][$key] = intval(str_replace("\x00", '', $value));803 $thisfile_asf_comments['track_number'][$key] = intval(str_replace("\x00", '', $value)); 797 804 } 798 805 } … … 800 807 801 808 case 'wm/track': 802 if (empty($thisfile_asf_comments['track '])) {803 $thisfile_asf_comments['track '] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value']));809 if (empty($thisfile_asf_comments['track_number'])) { 810 $thisfile_asf_comments['track_number'] = array(1 + $this->TrimConvert($thisfile_asf_extendedcontentdescriptionobject_contentdescriptor_current['value'])); 804 811 } 805 812 break; … … 971 978 } 972 979 } 973 if (isset($thisfile_asf_streambitrateproperties ['bitrate_records_count'])) {980 if (isset($thisfile_asf_streambitratepropertiesobject['bitrate_records_count'])) { 974 981 $ASFbitrateAudio = 0; 975 982 $ASFbitrateVideo = 0; 976 for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitrateproperties ['bitrate_records_count']; $BitrateRecordsCounter++) {983 for ($BitrateRecordsCounter = 0; $BitrateRecordsCounter < $thisfile_asf_streambitratepropertiesobject['bitrate_records_count']; $BitrateRecordsCounter++) { 977 984 if (isset($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter])) { 978 985 switch ($thisfile_asf_codeclistobject['codec_entries'][$BitrateRecordsCounter]['type_raw']) { 979 986 case 1: 980 $ASFbitrateVideo += $thisfile_asf_streambitrateproperties ['bitrate_records'][$BitrateRecordsCounter]['bitrate'];987 $ASFbitrateVideo += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate']; 981 988 break; 982 989 983 990 case 2: 984 $ASFbitrateAudio += $thisfile_asf_streambitrateproperties ['bitrate_records'][$BitrateRecordsCounter]['bitrate'];991 $ASFbitrateAudio += $thisfile_asf_streambitratepropertiesobject['bitrate_records'][$BitrateRecordsCounter]['bitrate']; 985 992 break; 986 993 … … 1441 1448 } 1442 1449 1450 /** 1451 * @param int $CodecListType 1452 * 1453 * @return string 1454 */ 1443 1455 public static function codecListObjectTypeLookup($CodecListType) { 1444 1456 static $lookup = array( … … 1451 1463 } 1452 1464 1465 /** 1466 * @return array 1467 */ 1453 1468 public static function KnownGUIDs() { 1454 1469 static $GUIDarray = array( … … 1565 1580 } 1566 1581 1582 /** 1583 * @param string $GUIDstring 1584 * 1585 * @return string|false 1586 */ 1567 1587 public static function GUIDname($GUIDstring) { 1568 1588 static $GUIDarray = array(); … … 1573 1593 } 1574 1594 1595 /** 1596 * @param int $id 1597 * 1598 * @return string 1599 */ 1575 1600 public static function ASFIndexObjectIndexTypeLookup($id) { 1576 1601 static $ASFIndexObjectIndexTypeLookup = array(); … … 1583 1608 } 1584 1609 1610 /** 1611 * @param string $GUIDstring 1612 * 1613 * @return string 1614 */ 1585 1615 public static function GUIDtoBytestring($GUIDstring) { 1586 1616 // Microsoft defines these 16-byte (128-bit) GUIDs in the strangest way: … … 1618 1648 } 1619 1649 1650 /** 1651 * @param string $Bytestring 1652 * 1653 * @return string 1654 */ 1620 1655 public static function BytestringToGUID($Bytestring) { 1621 $GUIDstring = str_pad(dechex(ord($Bytestring {3})), 2, '0', STR_PAD_LEFT);1622 $GUIDstring .= str_pad(dechex(ord($Bytestring {2})), 2, '0', STR_PAD_LEFT);1623 $GUIDstring .= str_pad(dechex(ord($Bytestring {1})), 2, '0', STR_PAD_LEFT);1624 $GUIDstring .= str_pad(dechex(ord($Bytestring {0})), 2, '0', STR_PAD_LEFT);1656 $GUIDstring = str_pad(dechex(ord($Bytestring[3])), 2, '0', STR_PAD_LEFT); 1657 $GUIDstring .= str_pad(dechex(ord($Bytestring[2])), 2, '0', STR_PAD_LEFT); 1658 $GUIDstring .= str_pad(dechex(ord($Bytestring[1])), 2, '0', STR_PAD_LEFT); 1659 $GUIDstring .= str_pad(dechex(ord($Bytestring[0])), 2, '0', STR_PAD_LEFT); 1625 1660 $GUIDstring .= '-'; 1626 $GUIDstring .= str_pad(dechex(ord($Bytestring {5})), 2, '0', STR_PAD_LEFT);1627 $GUIDstring .= str_pad(dechex(ord($Bytestring {4})), 2, '0', STR_PAD_LEFT);1661 $GUIDstring .= str_pad(dechex(ord($Bytestring[5])), 2, '0', STR_PAD_LEFT); 1662 $GUIDstring .= str_pad(dechex(ord($Bytestring[4])), 2, '0', STR_PAD_LEFT); 1628 1663 $GUIDstring .= '-'; 1629 $GUIDstring .= str_pad(dechex(ord($Bytestring {7})), 2, '0', STR_PAD_LEFT);1630 $GUIDstring .= str_pad(dechex(ord($Bytestring {6})), 2, '0', STR_PAD_LEFT);1664 $GUIDstring .= str_pad(dechex(ord($Bytestring[7])), 2, '0', STR_PAD_LEFT); 1665 $GUIDstring .= str_pad(dechex(ord($Bytestring[6])), 2, '0', STR_PAD_LEFT); 1631 1666 $GUIDstring .= '-'; 1632 $GUIDstring .= str_pad(dechex(ord($Bytestring {8})), 2, '0', STR_PAD_LEFT);1633 $GUIDstring .= str_pad(dechex(ord($Bytestring {9})), 2, '0', STR_PAD_LEFT);1667 $GUIDstring .= str_pad(dechex(ord($Bytestring[8])), 2, '0', STR_PAD_LEFT); 1668 $GUIDstring .= str_pad(dechex(ord($Bytestring[9])), 2, '0', STR_PAD_LEFT); 1634 1669 $GUIDstring .= '-'; 1635 $GUIDstring .= str_pad(dechex(ord($Bytestring {10})), 2, '0', STR_PAD_LEFT);1636 $GUIDstring .= str_pad(dechex(ord($Bytestring {11})), 2, '0', STR_PAD_LEFT);1637 $GUIDstring .= str_pad(dechex(ord($Bytestring {12})), 2, '0', STR_PAD_LEFT);1638 $GUIDstring .= str_pad(dechex(ord($Bytestring {13})), 2, '0', STR_PAD_LEFT);1639 $GUIDstring .= str_pad(dechex(ord($Bytestring {14})), 2, '0', STR_PAD_LEFT);1640 $GUIDstring .= str_pad(dechex(ord($Bytestring {15})), 2, '0', STR_PAD_LEFT);1670 $GUIDstring .= str_pad(dechex(ord($Bytestring[10])), 2, '0', STR_PAD_LEFT); 1671 $GUIDstring .= str_pad(dechex(ord($Bytestring[11])), 2, '0', STR_PAD_LEFT); 1672 $GUIDstring .= str_pad(dechex(ord($Bytestring[12])), 2, '0', STR_PAD_LEFT); 1673 $GUIDstring .= str_pad(dechex(ord($Bytestring[13])), 2, '0', STR_PAD_LEFT); 1674 $GUIDstring .= str_pad(dechex(ord($Bytestring[14])), 2, '0', STR_PAD_LEFT); 1675 $GUIDstring .= str_pad(dechex(ord($Bytestring[15])), 2, '0', STR_PAD_LEFT); 1641 1676 1642 1677 return strtoupper($GUIDstring); 1643 1678 } 1644 1679 1680 /** 1681 * @param int $FILETIME 1682 * @param bool $round 1683 * 1684 * @return float|int 1685 */ 1645 1686 public static function FILETIMEtoUNIXtime($FILETIME, $round=true) { 1646 1687 // FILETIME is a 64-bit unsigned integer representing … … 1654 1695 } 1655 1696 1697 /** 1698 * @param int $WMpictureType 1699 * 1700 * @return string 1701 */ 1656 1702 public static function WMpictureTypeLookup($WMpictureType) { 1657 1703 static $lookup = null; … … 1685 1731 } 1686 1732 1733 /** 1734 * @param string $asf_header_extension_object_data 1735 * @param int $unhandled_sections 1736 * 1737 * @return array 1738 */ 1687 1739 public function HeaderExtensionObjectDataParse(&$asf_header_extension_object_data, &$unhandled_sections) { 1688 1740 // http://msdn.microsoft.com/en-us/library/bb643323.aspx … … 1931 1983 } 1932 1984 1933 1985 /** 1986 * @param int $id 1987 * 1988 * @return string 1989 */ 1934 1990 public static function metadataLibraryObjectDataTypeLookup($id) { 1935 1991 static $lookup = array( … … 1945 2001 } 1946 2002 2003 /** 2004 * @param string $data 2005 * 2006 * @return array 2007 */ 1947 2008 public function ASF_WMpicture(&$data) { 1948 2009 //typedef struct _WMPicture{ … … 1995 2056 } 1996 2057 1997 1998 // Remove terminator 00 00 and convert UTF-16LE to Latin-1 2058 /** 2059 * Remove terminator 00 00 and convert UTF-16LE to Latin-1. 2060 * 2061 * @param string $string 2062 * 2063 * @return string 2064 */ 1999 2065 public static function TrimConvert($string) { 2000 2066 return trim(getid3_lib::iconv_fallback('UTF-16LE', 'ISO-8859-1', self::TrimTerm($string)), ' '); 2001 2067 } 2002 2068 2003 2004 // Remove terminator 00 00 2069 /** 2070 * Remove terminator 00 00. 2071 * 2072 * @param string $string 2073 * 2074 * @return string 2075 */ 2005 2076 public static function TrimTerm($string) { 2006 2077 // remove terminator, only if present (it should be, but...) -
trunk/src/wp-includes/ID3/module.audio-video.flv.php
r41196 r46112 2 2 ///////////////////////////////////////////////////////////////// 3 3 /// getID3() by James Heinrich <info@getid3.org> // 4 // available at http://getid3.sourceforge.net // 5 // or http://www.getid3.org // 6 // also https://github.com/JamesHeinrich/getID3 // 4 // available at https://github.com/JamesHeinrich/getID3 // 5 // or https://www.getid3.org // 6 // or http://getid3.sourceforge.net // 7 // see readme.txt for more details // 8 ///////////////////////////////////////////////////////////////// 9 // // 10 // module.audio-video.flv.php // 11 // module for analyzing Shockwave Flash Video files // 12 // dependencies: NONE // 13 // // 14 ///////////////////////////////////////////////////////////////// 7 15 // // 8 16 // FLV module by Seth Kaufman <sethØwhirl-i-gig*com> // 9 17 // // 10 18 // * version 0.1 (26 June 2005) // 11 // //12 19 // // 13 20 // * version 0.1.1 (15 July 2005) // … … 44 51 // improved AVCSequenceParameterSetReader::readData() // 45 52 // by Xander Schouwerwou <schouwerwouØgmail*com> // 46 // //47 /////////////////////////////////////////////////////////////////48 // //49 // module.audio-video.flv.php //50 // module for analyzing Shockwave Flash Video files //51 // dependencies: NONE //52 53 // /// 53 54 ///////////////////////////////////////////////////////////////// … … 74 75 define('H264_PROFILE_HIGH444_PREDICTIVE', 244); 75 76 76 class getid3_flv extends getid3_handler {77 77 class getid3_flv extends getid3_handler 78 { 78 79 const magic = 'FLV'; 79 80 80 public $max_frames = 100000; // break out of the loop if too many frames have been scanned; only scan this many if meta frame does not contain useful duration 81 81 /** 82 * Break out of the loop if too many frames have been scanned; only scan this 83 * many if meta frame does not contain useful duration. 84 * 85 * @var int 86 */ 87 public $max_frames = 100000; 88 89 /** 90 * @return bool 91 */ 82 92 public function Analyze() { 83 93 $info = &$this->getid3->info; … … 333 343 } 334 344 335 345 /** 346 * @param int $id 347 * 348 * @return string|false 349 */ 336 350 public static function audioFormatLookup($id) { 337 351 static $lookup = array( … … 356 370 } 357 371 372 /** 373 * @param int $id 374 * 375 * @return int|false 376 */ 358 377 public static function audioRateLookup($id) { 359 378 static $lookup = array( … … 366 385 } 367 386 387 /** 388 * @param int $id 389 * 390 * @return int|false 391 */ 368 392 public static function audioBitDepthLookup($id) { 369 393 static $lookup = array( … … 374 398 } 375 399 400 /** 401 * @param int $id 402 * 403 * @return string|false 404 */ 376 405 public static function videoCodecLookup($id) { 377 406 static $lookup = array( … … 387 416 } 388 417 389 class AMFStream { 418 class AMFStream 419 { 420 /** 421 * @var string 422 */ 390 423 public $bytes; 424 425 /** 426 * @var int 427 */ 391 428 public $pos; 392 429 430 /** 431 * @param string $bytes 432 */ 393 433 public function __construct(&$bytes) { 394 434 $this->bytes =& $bytes; … … 396 436 } 397 437 398 public function readByte() { 399 return getid3_lib::BigEndian2Int(substr($this->bytes, $this->pos++, 1)); 400 } 401 402 public function readInt() { 438 /** 439 * @return int 440 */ 441 public function readByte() { // 8-bit 442 return ord(substr($this->bytes, $this->pos++, 1)); 443 } 444 445 /** 446 * @return int 447 */ 448 public function readInt() { // 16-bit 403 449 return ($this->readByte() << 8) + $this->readByte(); 404 450 } 405 451 406 public function readLong() { 452 /** 453 * @return int 454 */ 455 public function readLong() { // 32-bit 407 456 return ($this->readByte() << 24) + ($this->readByte() << 16) + ($this->readByte() << 8) + $this->readByte(); 408 457 } 409 458 459 /** 460 * @return float|false 461 */ 410 462 public function readDouble() { 411 463 return getid3_lib::BigEndian2Float($this->read(8)); 412 464 } 413 465 466 /** 467 * @return string 468 */ 414 469 public function readUTF() { 415 470 $length = $this->readInt(); … … 417 472 } 418 473 474 /** 475 * @return string 476 */ 419 477 public function readLongUTF() { 420 478 $length = $this->readLong(); … … 422 480 } 423 481 482 /** 483 * @param int $length 484 * 485 * @return string 486 */ 424 487 public function read($length) { 425 488 $val = substr($this->bytes, $this->pos, $length); … … 428 491 } 429 492 493 /** 494 * @return int 495 */ 430 496 public function peekByte() { 431 497 $pos = $this->pos; … … 435 501 } 436 502 503 /** 504 * @return int 505 */ 437 506 public function peekInt() { 438 507 $pos = $this->pos; … … 442 511 } 443 512 513 /** 514 * @return int 515 */ 444 516 public function peekLong() { 445 517 $pos = $this->pos; … … 449 521 } 450 522 523 /** 524 * @return float|false 525 */ 451 526 public function peekDouble() { 452 527 $pos = $this->pos; … … 456 531 } 457 532 533 /** 534 * @return string 535 */ 458 536 public function peekUTF() { 459 537 $pos = $this->pos; … … 463 541 } 464 542 543 /** 544 * @return string 545 */ 465 546 public function peekLongUTF() { 466 547 $pos = $this->pos; … … 471 552 } 472 553 473 class AMFReader { 554 class AMFReader 555 { 556 /** 557 * @var AMFStream 558 */ 474 559 public $stream; 475 560 476 public function __construct(&$stream) { 477 $this->stream =& $stream; 478 } 479 561 /** 562 * @param AMFStream $stream 563 */ 564 public function __construct(AMFStream $stream) { 565 $this->stream = $stream; 566 } 567 568 /** 569 * @return mixed 570 */ 480 571 public function readData() { 481 572 $value = null; … … 548 639 } 549 640 641 /** 642 * @return float|false 643 */ 550 644 public function readDouble() { 551 645 return $this->stream->readDouble(); 552 646 } 553 647 648 /** 649 * @return bool 650 */ 554 651 public function readBoolean() { 555 652 return $this->stream->readByte() == 1; 556 653 } 557 654 655 /** 656 * @return string 657 */ 558 658 public function readString() { 559 659 return $this->stream->readUTF(); 560 660 } 561 661 662 /** 663 * @return array 664 */ 562 665 public function readObject() { 563 666 // Get highest numerical index - ignored … … 565 668 566 669 $data = array(); 670 $key = null; 567 671 568 672 while ($key = $this->stream->readUTF()) { … … 577 681 } 578 682 683 /** 684 * @return array 685 */ 579 686 public function readMixedArray() { 580 687 // Get highest numerical index - ignored … … 582 689 583 690 $data = array(); 691 $key = null; 584 692 585 693 while ($key = $this->stream->readUTF()) { 586 694 if (is_numeric($key)) { 587 $key = ( float) $key;695 $key = (int) $key; 588 696 } 589 697 $data[$key] = $this->readData(); … … 598 706 } 599 707 708 /** 709 * @return array 710 */ 600 711 public function readArray() { 601 712 $length = $this->stream->readLong(); … … 608 719 } 609 720 721 /** 722 * @return float|false 723 */ 610 724 public function readDate() { 611 725 $timestamp = $this->stream->readDouble(); … … 614 728 } 615 729 730 /** 731 * @return string 732 */ 616 733 public function readLongString() { 617 734 return $this->stream->readLongUTF(); 618 735 } 619 736 737 /** 738 * @return string 739 */ 620 740 public function readXML() { 621 741 return $this->stream->readLongUTF(); 622 742 } 623 743 744 /** 745 * @return array 746 */ 624 747 public function readTypedObject() { 625 748 $className = $this->stream->readUTF(); … … 628 751 } 629 752 630 class AVCSequenceParameterSetReader { 753 class AVCSequenceParameterSetReader 754 { 755 /** 756 * @var string 757 */ 631 758 public $sps; 632 759 public $start = 0; 633 760 public $currentBytes = 0; 634 761 public $currentBits = 0; 762 763 /** 764 * @var int 765 */ 635 766 public $width; 767 768 /** 769 * @var int 770 */ 636 771 public $height; 637 772 773 /** 774 * @param string $sps 775 */ 638 776 public function __construct($sps) { 639 777 $this->sps = $sps; … … 692 830 } 693 831 832 /** 833 * @param int $bits 834 */ 694 835 public function skipBits($bits) { 695 836 $newBits = $this->currentBits + $bits; … … 698 839 } 699 840 841 /** 842 * @return int 843 */ 700 844 public function getBit() { 701 845 $result = (getid3_lib::BigEndian2Int(substr($this->sps, $this->currentBytes, 1)) >> (7 - $this->currentBits)) & 0x01; … … 704 848 } 705 849 850 /** 851 * @param int $bits 852 * 853 * @return int 854 */ 706 855 public function getBits($bits) { 707 856 $result = 0; … … 712 861 } 713 862 863 /** 864 * @return int 865 */ 714 866 public function expGolombUe() { 715 867 $significantBits = 0; … … 727 879 } 728 880 881 /** 882 * @return int 883 */ 729 884 public function expGolombSe() { 730 885 $result = $this->expGolombUe(); … … 736 891 } 737 892 893 /** 894 * @return int 895 */ 738 896 public function getWidth() { 739 897 return $this->width; 740 898 } 741 899 900 /** 901 * @return int 902 */ 742 903 public function getHeight() { 743 904 return $this->height; -
trunk/src/wp-includes/ID3/module.audio-video.matroska.php
r41196 r46112 1 1 <?php 2 2 3 ///////////////////////////////////////////////////////////////// 3 4 /// getID3() by James Heinrich <info@getid3.org> // 4 // available at http://getid3.sourceforge.net // 5 // or http://www.getid3.org // 6 // also https://github.com/JamesHeinrich/getID3 // 7 ///////////////////////////////////////////////////////////////// 8 // See readme.txt for more details // 5 // available at https://github.com/JamesHeinrich/getID3 // 6 // or https://www.getid3.org // 7 // or http://getid3.sourceforge.net // 8 // see readme.txt for more details // 9 9 ///////////////////////////////////////////////////////////////// 10 10 // // … … 73 73 define('EBML_ID_FILEUID', 0x06AE); // [46][AE] -- Unique ID representing the file, as random as possible. 74 74 define('EBML_ID_CONTENTENCALGO', 0x07E1); // [47][E1] -- The encryption algorithm used. The value '0' means that the contents have not been encrypted but only signed. Predefined values: 75 define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the thedata was encrypted with.75 define('EBML_ID_CONTENTENCKEYID', 0x07E2); // [47][E2] -- For public key algorithms this is the ID of the public key the data was encrypted with. 76 76 define('EBML_ID_CONTENTSIGNATURE', 0x07E3); // [47][E3] -- A cryptographic signature of the contents. 77 77 define('EBML_ID_CONTENTSIGKEYID', 0x07E4); // [47][E4] -- This is the ID of the private key the data was signed with. … … 216 216 class getid3_matroska extends getid3_handler 217 217 { 218 // public options 219 public static $hide_clusters = true; // if true, do not return information about CLUSTER chunks, since there's a lot of them and they're not usually useful [default: TRUE] 220 public static $parse_whole_file = false; // true to parse the whole file, not only header [default: FALSE] 221 222 // private parser settings/placeholders 218 /** 219 * If true, do not return information about CLUSTER chunks, since there's a lot of them 220 * and they're not usually useful [default: TRUE]. 221 * 222 * @var bool 223 */ 224 public static $hide_clusters = true; 225 226 /** 227 * True to parse the whole file, not only header [default: FALSE]. 228 * 229 * @var bool 230 */ 231 public static $parse_whole_file = false; 232 233 /* 234 * Private parser settings/placeholders. 235 */ 223 236 private $EBMLbuffer = ''; 224 237 private $EBMLbuffer_offset = 0; … … 227 240 private $unuseful_elements = array(EBML_ID_CRC32, EBML_ID_VOID); 228 241 242 /** 243 * @return bool 244 */ 229 245 public function Analyze() 230 246 { … … 367 383 $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info[$header_data_key]; 368 384 if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) { 369 foreach ($getid3_temp->info['audio'] as $ key => $value) {370 $track_info[$ key] = $value;385 foreach ($getid3_temp->info['audio'] as $sub_key => $value) { 386 $track_info[$sub_key] = $value; 371 387 } 372 388 } … … 422 438 $info['matroska']['track_codec_parsed'][$trackarray['TrackNumber']] = $getid3_temp->info['ogg']; 423 439 if (isset($getid3_temp->info['audio']) && is_array($getid3_temp->info['audio'])) { 424 foreach ($getid3_temp->info['audio'] as $ key => $value) {425 $track_info[$ key] = $value;440 foreach ($getid3_temp->info['audio'] as $sub_key => $value) { 441 $track_info[$sub_key] = $value; 426 442 } 427 443 } … … 450 466 451 467 $parsed = getid3_riff::parseWAVEFORMATex($trackarray['CodecPrivate']); 452 foreach ($parsed as $ key => $value) {453 if ($ key != 'raw') {454 $track_info[$ key] = $value;468 foreach ($parsed as $sub_key => $value) { 469 if ($sub_key != 'raw') { 470 $track_info[$sub_key] = $value; 455 471 } 456 472 } … … 497 513 } 498 514 515 /** 516 * @param array $info 517 */ 499 518 private function parseEBML(&$info) { 500 519 // http://www.matroska.org/technical/specs/index.html#EBMLBasics … … 1229 1248 } 1230 1249 1250 /** 1251 * @param int $min_data 1252 * 1253 * @return bool 1254 */ 1231 1255 private function EnsureBufferHasEnoughData($min_data=1024) { 1232 1256 if (($this->current_offset - $this->EBMLbuffer_offset) >= ($this->EBMLbuffer_length - $min_data)) { … … 1250 1274 } 1251 1275 1276 /** 1277 * @return int|float|false 1278 */ 1252 1279 private function readEBMLint() { 1253 1280 $actual_offset = $this->current_offset - $this->EBMLbuffer_offset; … … 1282 1309 } 1283 1310 1311 /** 1312 * @param int $length 1313 * @param bool $check_buffer 1314 * 1315 * @return string|false 1316 */ 1284 1317 private function readEBMLelementData($length, $check_buffer=false) { 1285 1318 if ($check_buffer && !$this->EnsureBufferHasEnoughData($length)) { … … 1291 1324 } 1292 1325 1326 /** 1327 * @param array $element 1328 * @param int $parent_end 1329 * @param array|bool $get_data 1330 * 1331 * @return bool 1332 */ 1293 1333 private function getEBMLelement(&$element, $parent_end, $get_data=false) { 1294 1334 if ($this->current_offset >= $parent_end) { … … 1327 1367 } 1328 1368 1369 /** 1370 * @param string $type 1371 * @param int $line 1372 * @param array $element 1373 */ 1329 1374 private function unhandledElement($type, $line, $element) { 1330 1375 // warn only about unknown and missed elements, not about unuseful … … 1339 1384 } 1340 1385 1386 /** 1387 * @param array $SimpleTagArray 1388 * 1389 * @return bool 1390 */ 1341 1391 private function ExtractCommentsSimpleTag($SimpleTagArray) { 1342 1392 if (!empty($SimpleTagArray['SimpleTag'])) { … … 1354 1404 } 1355 1405 1406 /** 1407 * @param int $parent_end 1408 * 1409 * @return array 1410 */ 1356 1411 private function HandleEMBLSimpleTag($parent_end) { 1357 1412 $simpletag_entry = array(); … … 1384 1439 } 1385 1440 1441 /** 1442 * @param array $element 1443 * @param int $block_type 1444 * @param array $info 1445 * 1446 * @return array 1447 */ 1386 1448 private function HandleEMBLClusterBlock($element, $block_type, &$info) { 1387 1449 // http://www.matroska.org/technical/specs/index.html#block_structure … … 1447 1509 } 1448 1510 1511 /** 1512 * @param string $EBMLstring 1513 * 1514 * @return int|float|false 1515 */ 1449 1516 private static function EBML2Int($EBMLstring) { 1450 1517 // http://matroska.org/specs/ … … 1489 1556 } 1490 1557 1558 /** 1559 * @param int $EBMLdatestamp 1560 * 1561 * @return float 1562 */ 1491 1563 private static function EBMLdate2unix($EBMLdatestamp) { 1492 1564 // Date - signed 8 octets integer in nanoseconds with 0 indicating the precise beginning of the millennium (at 2001-01-01T00:00:00,000000000 UTC) … … 1495 1567 } 1496 1568 1569 /** 1570 * @param int $target_type 1571 * 1572 * @return string|int 1573 */ 1497 1574 public static function TargetTypeValue($target_type) { 1498 1575 // http://www.matroska.org/technical/specs/tagging/index.html … … 1510 1587 } 1511 1588 1589 /** 1590 * @param int $lacingtype 1591 * 1592 * @return string|int 1593 */ 1512 1594 public static function BlockLacingType($lacingtype) { 1513 1595 // http://matroska.org/technical/specs/index.html#block_structure … … 1522 1604 } 1523 1605 1606 /** 1607 * @param string $codecid 1608 * 1609 * @return string 1610 */ 1524 1611 public static function CodecIDtoCommonName($codecid) { 1525 1612 // http://www.matroska.org/technical/specs/codecid/index.html … … 1558 1645 } 1559 1646 1647 /** 1648 * @param int $value 1649 * 1650 * @return string 1651 */ 1560 1652 private static function EBMLidName($value) { 1561 1653 static $EBMLidList = array(); … … 1756 1848 } 1757 1849 1850 /** 1851 * @param int $value 1852 * 1853 * @return string 1854 */ 1758 1855 public static function displayUnit($value) { 1759 1856 // http://www.matroska.org/technical/specs/index.html#DisplayUnit … … 1767 1864 } 1768 1865 1866 /** 1867 * @param array $streams 1868 * 1869 * @return array 1870 */ 1769 1871 private static function getDefaultStreamInfo($streams) 1770 1872 { 1873 $stream = array(); 1771 1874 foreach (array_reverse($streams) as $stream) { 1772 1875 if ($stream['default']) { -
trunk/src/wp-includes/ID3/module.audio-video.quicktime.php
r41196 r46112 1 1 <?php 2 2 3 ///////////////////////////////////////////////////////////////// 3 4 /// getID3() by James Heinrich <info@getid3.org> // 4 // available at http://getid3.sourceforge.net // 5 // or http://www.getid3.org // 6 // also https://github.com/JamesHeinrich/getID3 // 7 ///////////////////////////////////////////////////////////////// 8 // See readme.txt for more details // 5 // available at https://github.com/JamesHeinrich/getID3 // 6 // or https://www.getid3.org // 7 // or http://getid3.sourceforge.net // 8 // see readme.txt for more details // 9 9 ///////////////////////////////////////////////////////////////// 10 10 // // … … 25 25 public $ParseAllPossibleAtoms = false; 26 26 27 /** 28 * @return bool 29 */ 27 30 public function Analyze() { 28 31 $info = &$this->getid3->info; … … 36 39 $offset = 0; 37 40 $atomcounter = 0; 38 $atom_data_read_buffer_size = max($this->getid3->option_fread_buffer_size * 1024, ($info['php_memory_limit'] ? round($info['php_memory_limit'] / 4) : 1024)); // set read buffer to 25% of PHP memory limit (if one is specified), otherwise use option_fread_buffer_size [default: 32MB]41 $atom_data_read_buffer_size = $info['php_memory_limit'] ? round($info['php_memory_limit'] / 4) : $this->getid3->option_fread_buffer_size * 1024; // set read buffer to 25% of PHP memory limit (if one is specified), otherwise use option_fread_buffer_size [default: 32MB] 39 42 while ($offset < $info['avdataend']) { 40 43 if (!getid3_lib::intValueSupported($offset)) { … … 163 166 $info['audio']['bitrate'] = $info['bitrate']; 164 167 } 168 if (!empty($info['bitrate']) && !empty($info['audio']['bitrate']) && empty($info['video']['bitrate']) && !empty($info['video']['frame_rate']) && !empty($info['video']['resolution_x']) && ($info['bitrate'] > $info['audio']['bitrate'])) { 169 $info['video']['bitrate'] = $info['bitrate'] - $info['audio']['bitrate']; 170 } 165 171 if (!empty($info['playtime_seconds']) && !isset($info['video']['frame_rate']) && !empty($info['quicktime']['stts_framecount'])) { 166 172 foreach ($info['quicktime']['stts_framecount'] as $key => $samples_count) { … … 194 200 $info['video']['dataformat'] = 'quicktime'; 195 201 } 202 if (isset($info['video']) && ($info['mime_type'] == 'audio/mp4') && empty($info['video']['resolution_x']) && empty($info['video']['resolution_y'])) { 203 unset($info['video']); 204 } 196 205 197 206 return true; 198 207 } 199 208 209 /** 210 * @param string $atomname 211 * @param int $atomsize 212 * @param string $atom_data 213 * @param int $baseoffset 214 * @param array $atomHierarchy 215 * @param bool $ParseAllPossibleAtoms 216 * 217 * @return array|false 218 */ 200 219 public function QuicktimeParseAtom($atomname, $atomsize, $atom_data, $baseoffset, &$atomHierarchy, $ParseAllPossibleAtoms) { 201 220 // http://developer.apple.com/techpubs/quicktime/qtdevdocs/APIREF/INDEX/atomalphaindex.htm … … 204 223 $info = &$this->getid3->info; 205 224 206 $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see http ://www.getid3.org/phpBB3/viewtopic.php?t=1717225 $atom_parent = end($atomHierarchy); // not array_pop($atomHierarchy); see https://www.getid3.org/phpBB3/viewtopic.php?t=1717 207 226 array_push($atomHierarchy, $atomname); 208 227 $atom_structure['hierarchy'] = implode(' ', $atomHierarchy); … … 210 229 $atom_structure['size'] = $atomsize; 211 230 $atom_structure['offset'] = $baseoffset; 212 switch ($atomname) { 213 case 'moov': // MOVie container atom 214 case 'trak': // TRAcK container atom 215 case 'clip': // CLIPping container atom 216 case 'matt': // track MATTe container atom 217 case 'edts': // EDiTS container atom 218 case 'tref': // Track REFerence container atom 219 case 'mdia': // MeDIA container atom 220 case 'minf': // Media INFormation container atom 221 case 'dinf': // Data INFormation container atom 222 case 'udta': // User DaTA container atom 223 case 'cmov': // Compressed MOVie container atom 224 case 'rmra': // Reference Movie Record Atom 225 case 'rmda': // Reference Movie Descriptor Atom 226 case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR) 227 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); 228 break; 229 230 case 'ilst': // Item LiST container atom 231 if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) { 232 // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted 233 $allnumericnames = true; 234 foreach ($atom_structure['subatoms'] as $subatomarray) { 235 if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) { 236 $allnumericnames = false; 237 break; 238 } 239 } 240 if ($allnumericnames) { 241 $newData = array(); 231 if (substr($atomname, 0, 3) == "\x00\x00\x00") { 232 // https://github.com/JamesHeinrich/getID3/issues/139 233 $atomname = getid3_lib::BigEndian2Int($atomname); 234 $atom_structure['name'] = $atomname; 235 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); 236 } else { 237 switch ($atomname) { 238 case 'moov': // MOVie container atom 239 case 'trak': // TRAcK container atom 240 case 'clip': // CLIPping container atom 241 case 'matt': // track MATTe container atom 242 case 'edts': // EDiTS container atom 243 case 'tref': // Track REFerence container atom 244 case 'mdia': // MeDIA container atom 245 case 'minf': // Media INFormation container atom 246 case 'dinf': // Data INFormation container atom 247 case 'udta': // User DaTA container atom 248 case 'cmov': // Compressed MOVie container atom 249 case 'rmra': // Reference Movie Record Atom 250 case 'rmda': // Reference Movie Descriptor Atom 251 case 'gmhd': // Generic Media info HeaDer atom (seen on QTVR) 252 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); 253 break; 254 255 case 'ilst': // Item LiST container atom 256 if ($atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms)) { 257 // some "ilst" atoms contain data atoms that have a numeric name, and the data is far more accessible if the returned array is compacted 258 $allnumericnames = true; 242 259 foreach ($atom_structure['subatoms'] as $subatomarray) { 243 foreach ($subatomarray['subatoms'] as $newData_subatomarray) { 244 unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']); 245 $newData[$subatomarray['name']] = $newData_subatomarray; 260 if (!is_integer($subatomarray['name']) || (count($subatomarray['subatoms']) != 1)) { 261 $allnumericnames = false; 246 262 break; 247 263 } 248 264 } 249 $atom_structure['data'] = $newData; 250 unset($atom_structure['subatoms']); 251 } 252 } 253 break; 254 255 case "\x00\x00\x00\x01": 256 case "\x00\x00\x00\x02": 257 case "\x00\x00\x00\x03": 258 case "\x00\x00\x00\x04": 259 case "\x00\x00\x00\x05": 260 $atomname = getid3_lib::BigEndian2Int($atomname); 261 $atom_structure['name'] = $atomname; 262 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); 263 break; 264 265 case 'stbl': // Sample TaBLe container atom 266 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); 267 $isVideo = false; 268 $framerate = 0; 269 $framecount = 0; 270 foreach ($atom_structure['subatoms'] as $key => $value_array) { 271 if (isset($value_array['sample_description_table'])) { 272 foreach ($value_array['sample_description_table'] as $key2 => $value_array2) { 273 if (isset($value_array2['data_format'])) { 274 switch ($value_array2['data_format']) { 275 case 'avc1': 276 case 'mp4v': 277 // video data 278 $isVideo = true; 279 break; 280 case 'mp4a': 281 // audio data 282 break; 265 if ($allnumericnames) { 266 $newData = array(); 267 foreach ($atom_structure['subatoms'] as $subatomarray) { 268 foreach ($subatomarray['subatoms'] as $newData_subatomarray) { 269 unset($newData_subatomarray['hierarchy'], $newData_subatomarray['name']); 270 $newData[$subatomarray['name']] = $newData_subatomarray; 271 break; 272 } 273 } 274 $atom_structure['data'] = $newData; 275 unset($atom_structure['subatoms']); 276 } 277 } 278 break; 279 280 case 'stbl': // Sample TaBLe container atom 281 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($atom_data, $baseoffset + 8, $atomHierarchy, $ParseAllPossibleAtoms); 282 $isVideo = false; 283 $framerate = 0; 284 $framecount = 0; 285 foreach ($atom_structure['subatoms'] as $key => $value_array) { 286 if (isset($value_array['sample_description_table'])) { 287 foreach ($value_array['sample_description_table'] as $key2 => $value_array2) { 288 if (isset($value_array2['data_format'])) { 289 switch ($value_array2['data_format']) { 290 case 'avc1': 291 case 'mp4v': 292 // video data 293 $isVideo = true; 294 break; 295 case 'mp4a': 296 // audio data 297 break; 298 } 299 } 300 } 301 } elseif (isset($value_array['time_to_sample_table'])) { 302 foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) { 303 if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) { 304 $framerate = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3); 305 $framecount = $value_array2['sample_count']; 283 306 } 284 307 } 285 308 } 286 } elseif (isset($value_array['time_to_sample_table'])) { 287 foreach ($value_array['time_to_sample_table'] as $key2 => $value_array2) { 288 if (isset($value_array2['sample_count']) && isset($value_array2['sample_duration']) && ($value_array2['sample_duration'] > 0)) { 289 $framerate = round($info['quicktime']['time_scale'] / $value_array2['sample_duration'], 3); 290 $framecount = $value_array2['sample_count']; 291 } 292 } 293 } 294 } 295 if ($isVideo && $framerate) { 296 $info['quicktime']['video']['frame_rate'] = $framerate; 297 $info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate']; 298 } 299 if ($isVideo && $framecount) { 300 $info['quicktime']['video']['frame_count'] = $framecount; 301 } 302 break; 303 304 305 case "\xA9".'alb': // ALBum 306 case "\xA9".'ART': // 307 case "\xA9".'art': // ARTist 308 case "\xA9".'aut': // 309 case "\xA9".'cmt': // CoMmenT 310 case "\xA9".'com': // COMposer 311 case "\xA9".'cpy': // 312 case "\xA9".'day': // content created year 313 case "\xA9".'dir': // 314 case "\xA9".'ed1': // 315 case "\xA9".'ed2': // 316 case "\xA9".'ed3': // 317 case "\xA9".'ed4': // 318 case "\xA9".'ed5': // 319 case "\xA9".'ed6': // 320 case "\xA9".'ed7': // 321 case "\xA9".'ed8': // 322 case "\xA9".'ed9': // 323 case "\xA9".'enc': // 324 case "\xA9".'fmt': // 325 case "\xA9".'gen': // GENre 326 case "\xA9".'grp': // GRouPing 327 case "\xA9".'hst': // 328 case "\xA9".'inf': // 329 case "\xA9".'lyr': // LYRics 330 case "\xA9".'mak': // 331 case "\xA9".'mod': // 332 case "\xA9".'nam': // full NAMe 333 case "\xA9".'ope': // 334 case "\xA9".'PRD': // 335 case "\xA9".'prf': // 336 case "\xA9".'req': // 337 case "\xA9".'src': // 338 case "\xA9".'swr': // 339 case "\xA9".'too': // encoder 340 case "\xA9".'trk': // TRacK 341 case "\xA9".'url': // 342 case "\xA9".'wrn': // 343 case "\xA9".'wrt': // WRiTer 344 case '----': // itunes specific 345 case 'aART': // Album ARTist 346 case 'akID': // iTunes store account type 347 case 'apID': // Purchase Account 348 case 'atID': // 349 case 'catg': // CaTeGory 350 case 'cmID': // 351 case 'cnID': // 352 case 'covr': // COVeR artwork 353 case 'cpil': // ComPILation 354 case 'cprt': // CoPyRighT 355 case 'desc': // DESCription 356 case 'disk': // DISK number 357 case 'egid': // Episode Global ID 358 case 'geID': // 359 case 'gnre': // GeNRE 360 case 'hdvd': // HD ViDeo 361 case 'keyw': // KEYWord 362 case 'ldes': // Long DEScription 363 case 'pcst': // PodCaST 364 case 'pgap': // GAPless Playback 365 case 'plID': // 366 case 'purd': // PURchase Date 367 case 'purl': // Podcast URL 368 case 'rati': // 369 case 'rndu': // 370 case 'rpdu': // 371 case 'rtng': // RaTiNG 372 case 'sfID': // iTunes store country 373 case 'soaa': // SOrt Album Artist 374 case 'soal': // SOrt ALbum 375 case 'soar': // SOrt ARtist 376 case 'soco': // SOrt COmposer 377 case 'sonm': // SOrt NaMe 378 case 'sosn': // SOrt Show Name 379 case 'stik': // 380 case 'tmpo': // TeMPO (BPM) 381 case 'trkn': // TRacK Number 382 case 'tven': // tvEpisodeID 383 case 'tves': // TV EpiSode 384 case 'tvnn': // TV Network Name 385 case 'tvsh': // TV SHow Name 386 case 'tvsn': // TV SeasoN 387 if ($atom_parent == 'udta') { 388 // User data atom handler 389 $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); 390 $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); 391 $atom_structure['data'] = substr($atom_data, 4); 392 393 $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); 394 if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { 395 $info['comments']['language'][] = $atom_structure['language']; 396 } 397 } else { 398 // Apple item list box atom handler 399 $atomoffset = 0; 400 if (substr($atom_data, 2, 2) == "\x10\xB5") { 401 // not sure what it means, but observed on iPhone4 data. 402 // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data 403 while ($atomoffset < strlen($atom_data)) { 404 $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 2)); 405 $boxsmalltype = substr($atom_data, $atomoffset + 2, 2); 406 $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize); 407 if ($boxsmallsize <= 1) { 408 $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset)); 409 $atom_structure['data'] = null; 410 $atomoffset = strlen($atom_data); 411 break; 412 } 413 switch ($boxsmalltype) { 414 case "\x10\xB5": 415 $atom_structure['data'] = $boxsmalldata; 416 break; 417 default: 418 $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset); 419 $atom_structure['data'] = $atom_data; 420 break; 421 } 422 $atomoffset += (4 + $boxsmallsize); 309 } 310 if ($isVideo && $framerate) { 311 $info['quicktime']['video']['frame_rate'] = $framerate; 312 $info['video']['frame_rate'] = $info['quicktime']['video']['frame_rate']; 313 } 314 if ($isVideo && $framecount) { 315 $info['quicktime']['video']['frame_count'] = $framecount; 316 } 317 break; 318 319 320 case "\xA9".'alb': // ALBum 321 case "\xA9".'ART': // 322 case "\xA9".'art': // ARTist 323 case "\xA9".'aut': // 324 case "\xA9".'cmt': // CoMmenT 325 case "\xA9".'com': // COMposer 326 case "\xA9".'cpy': // 327 case "\xA9".'day': // content created year 328 case "\xA9".'dir': // 329 case "\xA9".'ed1': // 330 case "\xA9".'ed2': // 331 case "\xA9".'ed3': // 332 case "\xA9".'ed4': // 333 case "\xA9".'ed5': // 334 case "\xA9".'ed6': // 335 case "\xA9".'ed7': // 336 case "\xA9".'ed8': // 337 case "\xA9".'ed9': // 338 case "\xA9".'enc': // 339 case "\xA9".'fmt': // 340 case "\xA9".'gen': // GENre 341 case "\xA9".'grp': // GRouPing 342 case "\xA9".'hst': // 343 case "\xA9".'inf': // 344 case "\xA9".'lyr': // LYRics 345 case "\xA9".'mak': // 346 case "\xA9".'mod': // 347 case "\xA9".'nam': // full NAMe 348 case "\xA9".'ope': // 349 case "\xA9".'PRD': // 350 case "\xA9".'prf': // 351 case "\xA9".'req': // 352 case "\xA9".'src': // 353 case "\xA9".'swr': // 354 case "\xA9".'too': // encoder 355 case "\xA9".'trk': // TRacK 356 case "\xA9".'url': // 357 case "\xA9".'wrn': // 358 case "\xA9".'wrt': // WRiTer 359 case '----': // itunes specific 360 case 'aART': // Album ARTist 361 case 'akID': // iTunes store account type 362 case 'apID': // Purchase Account 363 case 'atID': // 364 case 'catg': // CaTeGory 365 case 'cmID': // 366 case 'cnID': // 367 case 'covr': // COVeR artwork 368 case 'cpil': // ComPILation 369 case 'cprt': // CoPyRighT 370 case 'desc': // DESCription 371 case 'disk': // DISK number 372 case 'egid': // Episode Global ID 373 case 'geID': // 374 case 'gnre': // GeNRE 375 case 'hdvd': // HD ViDeo 376 case 'keyw': // KEYWord 377 case 'ldes': // Long DEScription 378 case 'pcst': // PodCaST 379 case 'pgap': // GAPless Playback 380 case 'plID': // 381 case 'purd': // PURchase Date 382 case 'purl': // Podcast URL 383 case 'rati': // 384 case 'rndu': // 385 case 'rpdu': // 386 case 'rtng': // RaTiNG 387 case 'sfID': // iTunes store country 388 case 'soaa': // SOrt Album Artist 389 case 'soal': // SOrt ALbum 390 case 'soar': // SOrt ARtist 391 case 'soco': // SOrt COmposer 392 case 'sonm': // SOrt NaMe 393 case 'sosn': // SOrt Show Name 394 case 'stik': // 395 case 'tmpo': // TeMPO (BPM) 396 case 'trkn': // TRacK Number 397 case 'tven': // tvEpisodeID 398 case 'tves': // TV EpiSode 399 case 'tvnn': // TV Network Name 400 case 'tvsh': // TV SHow Name 401 case 'tvsn': // TV SeasoN 402 if ($atom_parent == 'udta') { 403 // User data atom handler 404 $atom_structure['data_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); 405 $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); 406 $atom_structure['data'] = substr($atom_data, 4); 407 408 $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); 409 if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { 410 $info['comments']['language'][] = $atom_structure['language']; 423 411 } 424 412 } else { 425 while ($atomoffset < strlen($atom_data)) { 426 $boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4)); 427 $boxtype = substr($atom_data, $atomoffset + 4, 4); 428 $boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8); 429 if ($boxsize <= 1) { 430 $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset)); 431 $atom_structure['data'] = null; 432 $atomoffset = strlen($atom_data); 433 break; 413 // Apple item list box atom handler 414 $atomoffset = 0; 415 if (substr($atom_data, 2, 2) == "\x10\xB5") { 416 // not sure what it means, but observed on iPhone4 data. 417 // Each $atom_data has 2 bytes of datasize, plus 0x10B5, then data 418 while ($atomoffset < strlen($atom_data)) { 419 $boxsmallsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 2)); 420 $boxsmalltype = substr($atom_data, $atomoffset + 2, 2); 421 $boxsmalldata = substr($atom_data, $atomoffset + 4, $boxsmallsize); 422 if ($boxsmallsize <= 1) { 423 $this->warning('Invalid QuickTime atom smallbox size "'.$boxsmallsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset)); 424 $atom_structure['data'] = null; 425 $atomoffset = strlen($atom_data); 426 break; 427 } 428 switch ($boxsmalltype) { 429 case "\x10\xB5": 430 $atom_structure['data'] = $boxsmalldata; 431 break; 432 default: 433 $this->warning('Unknown QuickTime smallbox type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxsmalltype).'" ('.trim(getid3_lib::PrintHexBytes($boxsmalltype)).') at offset '.$baseoffset); 434 $atom_structure['data'] = $atom_data; 435 break; 436 } 437 $atomoffset += (4 + $boxsmallsize); 434 438 } 435 $atomoffset += $boxsize; 436 437 switch ($boxtype) { 438 case 'mean': 439 case 'name': 440 $atom_structure[$boxtype] = substr($boxdata, 4); 439 } else { 440 while ($atomoffset < strlen($atom_data)) { 441 $boxsize = getid3_lib::BigEndian2Int(substr($atom_data, $atomoffset, 4)); 442 $boxtype = substr($atom_data, $atomoffset + 4, 4); 443 $boxdata = substr($atom_data, $atomoffset + 8, $boxsize - 8); 444 if ($boxsize <= 1) { 445 $this->warning('Invalid QuickTime atom box size "'.$boxsize.'" in atom "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $atomname).'" at offset: '.($atom_structure['offset'] + $atomoffset)); 446 $atom_structure['data'] = null; 447 $atomoffset = strlen($atom_data); 441 448 break; 442 443 case 'data': 444 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($boxdata, 0, 1)); 445 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata, 1, 3)); 446 switch ($atom_structure['flags_raw']) { 447 case 0: // data flag 448 case 21: // tmpo/cpil flag 449 switch ($atomname) { 450 case 'cpil': 451 case 'hdvd': 452 case 'pcst': 453 case 'pgap': 454 // 8-bit integer (boolean) 455 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); 456 break; 457 458 case 'tmpo': 459 // 16-bit integer 460 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2)); 461 break; 462 463 case 'disk': 464 case 'trkn': 465 // binary 466 $num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2)); 467 $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2)); 468 $atom_structure['data'] = empty($num) ? '' : $num; 469 $atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total; 470 break; 471 472 case 'gnre': 473 // enum 474 $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); 475 $atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1); 476 break; 477 478 case 'rtng': 479 // 8-bit integer 480 $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); 481 $atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]); 482 break; 483 484 case 'stik': 485 // 8-bit integer (enum) 486 $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); 487 $atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]); 488 break; 489 490 case 'sfID': 491 // 32-bit integer 492 $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); 493 $atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]); 494 break; 495 496 case 'egid': 497 case 'purl': 498 $atom_structure['data'] = substr($boxdata, 8); 499 break; 500 501 case 'plID': 502 // 64-bit integer 503 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8)); 504 break; 505 506 case 'covr': 507 $atom_structure['data'] = substr($boxdata, 8); 449 } 450 $atomoffset += $boxsize; 451 452 switch ($boxtype) { 453 case 'mean': 454 case 'name': 455 $atom_structure[$boxtype] = substr($boxdata, 4); 456 break; 457 458 case 'data': 459 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($boxdata, 0, 1)); 460 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($boxdata, 1, 3)); 461 switch ($atom_structure['flags_raw']) { 462 case 0: // data flag 463 case 21: // tmpo/cpil flag 464 switch ($atomname) { 465 case 'cpil': 466 case 'hdvd': 467 case 'pcst': 468 case 'pgap': 469 // 8-bit integer (boolean) 470 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); 471 break; 472 473 case 'tmpo': 474 // 16-bit integer 475 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 2)); 476 break; 477 478 case 'disk': 479 case 'trkn': 480 // binary 481 $num = getid3_lib::BigEndian2Int(substr($boxdata, 10, 2)); 482 $num_total = getid3_lib::BigEndian2Int(substr($boxdata, 12, 2)); 483 $atom_structure['data'] = empty($num) ? '' : $num; 484 $atom_structure['data'] .= empty($num_total) ? '' : '/'.$num_total; 485 break; 486 487 case 'gnre': 488 // enum 489 $GenreID = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); 490 $atom_structure['data'] = getid3_id3v1::LookupGenreName($GenreID - 1); 491 break; 492 493 case 'rtng': 494 // 8-bit integer 495 $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); 496 $atom_structure['data'] = $this->QuicktimeContentRatingLookup($atom_structure[$atomname]); 497 break; 498 499 case 'stik': 500 // 8-bit integer (enum) 501 $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 1)); 502 $atom_structure['data'] = $this->QuicktimeSTIKLookup($atom_structure[$atomname]); 503 break; 504 505 case 'sfID': 506 // 32-bit integer 507 $atom_structure[$atomname] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); 508 $atom_structure['data'] = $this->QuicktimeStoreFrontCodeLookup($atom_structure[$atomname]); 509 break; 510 511 case 'egid': 512 case 'purl': 513 $atom_structure['data'] = substr($boxdata, 8); 514 break; 515 516 case 'plID': 517 // 64-bit integer 518 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 8)); 519 break; 520 521 case 'covr': 522 $atom_structure['data'] = substr($boxdata, 8); 523 // not a foolproof check, but better than nothing 524 if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) { 525 $atom_structure['image_mime'] = 'image/jpeg'; 526 } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) { 527 $atom_structure['image_mime'] = 'image/png'; 528 } elseif (preg_match('#^GIF#', $atom_structure['data'])) { 529 $atom_structure['image_mime'] = 'image/gif'; 530 } 531 break; 532 533 case 'atID': 534 case 'cnID': 535 case 'geID': 536 case 'tves': 537 case 'tvsn': 538 default: 539 // 32-bit integer 540 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4)); 541 } 542 break; 543 544 case 1: // text flag 545 case 13: // image flag 546 default: 547 $atom_structure['data'] = substr($boxdata, 8); 548 if ($atomname == 'covr') { 508 549 // not a foolproof check, but better than nothing 509 550 if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) { … … 514 555 $atom_structure['image_mime'] = 'image/gif'; 515 556 } 516 break;517 518 case 'atID':519 case 'cnID':520 case 'geID':521 case 'tves':522 case 'tvsn':523 default:524 // 32-bit integer525 $atom_structure['data'] = getid3_lib::BigEndian2Int(substr($boxdata, 8, 4));526 }527 break;528 529 case 1: // text flag530 case 13: // image flag531 default:532 $atom_structure['data'] = substr($boxdata, 8);533 if ($atomname == 'covr') {534 // not a foolproof check, but better than nothing535 if (preg_match('#^\\xFF\\xD8\\xFF#', $atom_structure['data'])) {536 $atom_structure['image_mime'] = 'image/jpeg';537 } elseif (preg_match('#^\\x89\\x50\\x4E\\x47\\x0D\\x0A\\x1A\\x0A#', $atom_structure['data'])) {538 $atom_structure['image_mime'] = 'image/png';539 } elseif (preg_match('#^GIF#', $atom_structure['data'])) {540 $atom_structure['image_mime'] = 'image/gif';541 557 } 542 }543 break; 544 545 }546 break; 547 548 default:549 $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset);550 $atom_structure['data'] = $atom_data; 551 558 break; 559 560 } 561 break; 562 563 default: 564 $this->warning('Unknown QuickTime box type: "'.preg_replace('#[^a-zA-Z0-9 _\\-]#', '?', $boxtype).'" ('.trim(getid3_lib::PrintHexBytes($boxtype)).') at offset '.$baseoffset); 565 $atom_structure['data'] = $atom_data; 566 567 } 552 568 } 553 569 } 554 570 } 555 } 556 $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']); 557 break; 558 559 560 case 'play': // auto-PLAY atom 561 $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 562 563 $info['quicktime']['autoplay'] = $atom_structure['autoplay']; 564 break; 565 566 567 case 'WLOC': // Window LOCation atom 568 $atom_structure['location_x'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); 569 $atom_structure['location_y'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); 570 break; 571 572 573 case 'LOOP': // LOOPing atom 574 case 'SelO': // play SELection Only atom 575 case 'AllF': // play ALL Frames atom 576 $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data); 577 break; 578 579 580 case 'name': // 581 case 'MCPS': // Media Cleaner PRo 582 case '@PRM': // adobe PReMiere version 583 case '@PRQ': // adobe PRemiere Quicktime version 584 $atom_structure['data'] = $atom_data; 585 break; 586 587 588 case 'cmvd': // Compressed MooV Data atom 589 // Code by ubergeekØubergeek*tv based on information from 590 // http://developer.apple.com/quicktime/icefloe/dispatch012.html 591 $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); 592 593 $CompressedFileData = substr($atom_data, 4); 594 if ($UncompressedHeader = @gzuncompress($CompressedFileData)) { 595 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms); 596 } else { 597 $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']); 598 } 599 break; 600 601 602 case 'dcom': // Data COMpression atom 603 $atom_structure['compression_id'] = $atom_data; 604 $atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data); 605 break; 606 607 608 case 'rdrf': // Reference movie Data ReFerence atom 609 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 610 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); 611 $atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001); 612 613 $atom_structure['reference_type_name'] = substr($atom_data, 4, 4); 614 $atom_structure['reference_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); 615 switch ($atom_structure['reference_type_name']) { 616 case 'url ': 617 $atom_structure['url'] = $this->NoNullString(substr($atom_data, 12)); 618 break; 619 620 case 'alis': 621 $atom_structure['file_alias'] = substr($atom_data, 12); 622 break; 623 624 case 'rsrc': 625 $atom_structure['resource_alias'] = substr($atom_data, 12); 626 break; 627 628 default: 629 $atom_structure['data'] = substr($atom_data, 12); 630 break; 631 } 632 break; 633 634 635 case 'rmqu': // Reference Movie QUality atom 636 $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data); 637 break; 638 639 640 case 'rmcs': // Reference Movie Cpu Speed atom 641 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 642 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 643 $atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); 644 break; 645 646 647 case 'rmvc': // Reference Movie Version Check atom 648 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 649 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 650 $atom_structure['gestalt_selector'] = substr($atom_data, 4, 4); 651 $atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); 652 $atom_structure['gestalt_value'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); 653 $atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2)); 654 break; 655 656 657 case 'rmcd': // Reference Movie Component check atom 658 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 659 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 660 $atom_structure['component_type'] = substr($atom_data, 4, 4); 661 $atom_structure['component_subtype'] = substr($atom_data, 8, 4); 662 $atom_structure['component_manufacturer'] = substr($atom_data, 12, 4); 663 $atom_structure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); 664 $atom_structure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4)); 665 $atom_structure['component_min_version'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4)); 666 break; 667 668 669 case 'rmdr': // Reference Movie Data Rate atom 670 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 671 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 672 $atom_structure['data_rate'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 673 674 $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10; 675 break; 676 677 678 case 'rmla': // Reference Movie Language Atom 679 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 680 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 681 $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); 682 683 $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); 684 if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { 685 $info['comments']['language'][] = $atom_structure['language']; 686 } 687 break; 688 689 690 case 'rmla': // Reference Movie Language Atom 691 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 692 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 693 $atom_structure['track_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); 694 break; 695 696 697 case 'ptv ': // Print To Video - defines a movie's full screen mode 698 // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm 699 $atom_structure['display_size_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); 700 $atom_structure['reserved_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000 701 $atom_structure['reserved_2'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000 702 $atom_structure['slide_show_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1)); 703 $atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1)); 704 705 $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag']; 706 $atom_structure['flags']['slide_show'] = (bool) $atom_structure['slide_show_flag']; 707 708 $ptv_lookup[0] = 'normal'; 709 $ptv_lookup[1] = 'double'; 710 $ptv_lookup[2] = 'half'; 711 $ptv_lookup[3] = 'full'; 712 $ptv_lookup[4] = 'current'; 713 if (isset($ptv_lookup[$atom_structure['display_size_raw']])) { 714 $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']]; 715 } else { 716 $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')'); 717 } 718 break; 719 720 721 case 'stsd': // Sample Table Sample Description atom 722 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 723 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 724 $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 725 726 // see: https://github.com/JamesHeinrich/getID3/issues/111 727 // Some corrupt files have been known to have high bits set in the number_entries field 728 // This field shouldn't really need to be 32-bits, values stores are likely in the range 1-100000 729 // Workaround: mask off the upper byte and throw a warning if it's nonzero 730 if ($atom_structure['number_entries'] > 0x000FFFFF) { 731 if ($atom_structure['number_entries'] > 0x00FFFFFF) { 732 $this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Ignoring upper byte and interpreting this as 0x'.getid3_lib::PrintHexBytes(substr($atom_data, 5, 3), true, false).' = '.($atom_structure['number_entries'] & 0x00FFFFFF)); 733 $atom_structure['number_entries'] = ($atom_structure['number_entries'] & 0x00FFFFFF); 571 $this->CopyToAppropriateCommentsSection($atomname, $atom_structure['data'], $atom_structure['name']); 572 break; 573 574 575 case 'play': // auto-PLAY atom 576 $atom_structure['autoplay'] = (bool) getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 577 578 $info['quicktime']['autoplay'] = $atom_structure['autoplay']; 579 break; 580 581 582 case 'WLOC': // Window LOCation atom 583 $atom_structure['location_x'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); 584 $atom_structure['location_y'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); 585 break; 586 587 588 case 'LOOP': // LOOPing atom 589 case 'SelO': // play SELection Only atom 590 case 'AllF': // play ALL Frames atom 591 $atom_structure['data'] = getid3_lib::BigEndian2Int($atom_data); 592 break; 593 594 595 case 'name': // 596 case 'MCPS': // Media Cleaner PRo 597 case '@PRM': // adobe PReMiere version 598 case '@PRQ': // adobe PRemiere Quicktime version 599 $atom_structure['data'] = $atom_data; 600 break; 601 602 603 case 'cmvd': // Compressed MooV Data atom 604 // Code by ubergeekØubergeek*tv based on information from 605 // http://developer.apple.com/quicktime/icefloe/dispatch012.html 606 $atom_structure['unCompressedSize'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 4)); 607 608 $CompressedFileData = substr($atom_data, 4); 609 if ($UncompressedHeader = @gzuncompress($CompressedFileData)) { 610 $atom_structure['subatoms'] = $this->QuicktimeParseContainerAtom($UncompressedHeader, 0, $atomHierarchy, $ParseAllPossibleAtoms); 734 611 } else { 735 $this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Please report this to info@getid3.org referencing bug report #111'); 736 } 737 } 738 739 $stsdEntriesDataOffset = 8; 740 for ($i = 0; $i < $atom_structure['number_entries']; $i++) { 741 $atom_structure['sample_description_table'][$i]['size'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 4)); 742 $stsdEntriesDataOffset += 4; 743 $atom_structure['sample_description_table'][$i]['data_format'] = substr($atom_data, $stsdEntriesDataOffset, 4); 744 $stsdEntriesDataOffset += 4; 745 $atom_structure['sample_description_table'][$i]['reserved'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 6)); 746 $stsdEntriesDataOffset += 6; 747 $atom_structure['sample_description_table'][$i]['reference_index'] = getid3_lib::BigEndian2Int(substr($atom_data, $stsdEntriesDataOffset, 2)); 748 $stsdEntriesDataOffset += 2; 749 $atom_structure['sample_description_table'][$i]['data'] = substr($atom_data, $stsdEntriesDataOffset, ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2)); 750 $stsdEntriesDataOffset += ($atom_structure['sample_description_table'][$i]['size'] - 4 - 4 - 6 - 2); 751 752 $atom_structure['sample_description_table'][$i]['encoder_version'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 0, 2)); 753 $atom_structure['sample_description_table'][$i]['encoder_revision'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 2, 2)); 754 $atom_structure['sample_description_table'][$i]['encoder_vendor'] = substr($atom_structure['sample_description_table'][$i]['data'], 4, 4); 755 756 switch ($atom_structure['sample_description_table'][$i]['encoder_vendor']) { 757 758 case "\x00\x00\x00\x00": 759 // audio tracks 760 $atom_structure['sample_description_table'][$i]['audio_channels'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 2)); 761 $atom_structure['sample_description_table'][$i]['audio_bit_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 10, 2)); 762 $atom_structure['sample_description_table'][$i]['audio_compression_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 2)); 763 $atom_structure['sample_description_table'][$i]['audio_packet_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 14, 2)); 764 $atom_structure['sample_description_table'][$i]['audio_sample_rate'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 16, 4)); 765 766 // video tracks 767 // http://developer.apple.com/library/mac/#documentation/QuickTime/QTFF/QTFFChap3/qtff3.html 768 $atom_structure['sample_description_table'][$i]['temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4)); 769 $atom_structure['sample_description_table'][$i]['spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4)); 770 $atom_structure['sample_description_table'][$i]['width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2)); 771 $atom_structure['sample_description_table'][$i]['height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2)); 772 $atom_structure['sample_description_table'][$i]['resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4)); 773 $atom_structure['sample_description_table'][$i]['resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4)); 774 $atom_structure['sample_description_table'][$i]['data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 4)); 775 $atom_structure['sample_description_table'][$i]['frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 36, 2)); 776 $atom_structure['sample_description_table'][$i]['compressor_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 38, 4); 777 $atom_structure['sample_description_table'][$i]['pixel_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 42, 2)); 778 $atom_structure['sample_description_table'][$i]['color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 44, 2)); 779 780 switch ($atom_structure['sample_description_table'][$i]['data_format']) { 781 case '2vuY': 782 case 'avc1': 783 case 'cvid': 784 case 'dvc ': 785 case 'dvcp': 786 case 'gif ': 787 case 'h263': 788 case 'jpeg': 789 case 'kpcd': 790 case 'mjpa': 791 case 'mjpb': 792 case 'mp4v': 793 case 'png ': 794 case 'raw ': 795 case 'rle ': 796 case 'rpza': 797 case 'smc ': 798 case 'SVQ1': 799 case 'SVQ3': 800 case 'tiff': 801 case 'v210': 802 case 'v216': 803 case 'v308': 804 case 'v408': 805 case 'v410': 806 case 'yuv2': 807 $info['fileformat'] = 'mp4'; 808 $info['video']['fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; 809 // http://www.getid3.org/phpBB3/viewtopic.php?t=1550 810 //if ((!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['width'])) && (empty($info['video']['resolution_x']) || empty($info['video']['resolution_y']) || (number_format($info['video']['resolution_x'], 6) != number_format(round($info['video']['resolution_x']), 6)) || (number_format($info['video']['resolution_y'], 6) != number_format(round($info['video']['resolution_y']), 6)))) { // ugly check for floating point numbers 811 if (!empty($atom_structure['sample_description_table'][$i]['width']) && !empty($atom_structure['sample_description_table'][$i]['height'])) { 812 // assume that values stored here are more important than values stored in [tkhd] atom 813 $info['video']['resolution_x'] = $atom_structure['sample_description_table'][$i]['width']; 814 $info['video']['resolution_y'] = $atom_structure['sample_description_table'][$i]['height']; 815 $info['quicktime']['video']['resolution_x'] = $info['video']['resolution_x']; 816 $info['quicktime']['video']['resolution_y'] = $info['video']['resolution_y']; 817 } 818 break; 819 820 case 'qtvr': 821 $info['video']['dataformat'] = 'quicktimevr'; 822 break; 823 824 case 'mp4a': 825 default: 826 $info['quicktime']['audio']['codec'] = $this->QuicktimeAudioCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); 827 $info['quicktime']['audio']['sample_rate'] = $atom_structure['sample_description_table'][$i]['audio_sample_rate']; 828 $info['quicktime']['audio']['channels'] = $atom_structure['sample_description_table'][$i]['audio_channels']; 829 $info['quicktime']['audio']['bit_depth'] = $atom_structure['sample_description_table'][$i]['audio_bit_depth']; 830 $info['audio']['codec'] = $info['quicktime']['audio']['codec']; 831 $info['audio']['sample_rate'] = $info['quicktime']['audio']['sample_rate']; 832 $info['audio']['channels'] = $info['quicktime']['audio']['channels']; 833 $info['audio']['bits_per_sample'] = $info['quicktime']['audio']['bit_depth']; 834 switch ($atom_structure['sample_description_table'][$i]['data_format']) { 835 case 'raw ': // PCM 836 case 'alac': // Apple Lossless Audio Codec 837 $info['audio']['lossless'] = true; 838 break; 839 default: 840 $info['audio']['lossless'] = false; 841 break; 842 } 843 break; 844 } 612 $this->warning('Error decompressing compressed MOV atom at offset '.$atom_structure['offset']); 613 } 614 break; 615 616 617 case 'dcom': // Data COMpression atom 618 $atom_structure['compression_id'] = $atom_data; 619 $atom_structure['compression_text'] = $this->QuicktimeDCOMLookup($atom_data); 620 break; 621 622 623 case 'rdrf': // Reference movie Data ReFerence atom 624 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 625 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); 626 $atom_structure['flags']['internal_data'] = (bool) ($atom_structure['flags_raw'] & 0x000001); 627 628 $atom_structure['reference_type_name'] = substr($atom_data, 4, 4); 629 $atom_structure['reference_length'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); 630 switch ($atom_structure['reference_type_name']) { 631 case 'url ': 632 $atom_structure['url'] = $this->NoNullString(substr($atom_data, 12)); 845 633 break; 846 634 635 case 'alis': 636 $atom_structure['file_alias'] = substr($atom_data, 12); 637 break; 638 639 case 'rsrc': 640 $atom_structure['resource_alias'] = substr($atom_data, 12); 641 break; 642 847 643 default: 848 switch ($atom_structure['sample_description_table'][$i]['data_format']) { 849 case 'mp4s': 850 $info['fileformat'] = 'mp4'; 851 break; 852 853 default: 854 // video atom 855 $atom_structure['sample_description_table'][$i]['video_temporal_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 8, 4)); 856 $atom_structure['sample_description_table'][$i]['video_spatial_quality'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 12, 4)); 857 $atom_structure['sample_description_table'][$i]['video_frame_width'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 16, 2)); 858 $atom_structure['sample_description_table'][$i]['video_frame_height'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 18, 2)); 859 $atom_structure['sample_description_table'][$i]['video_resolution_x'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 20, 4)); 860 $atom_structure['sample_description_table'][$i]['video_resolution_y'] = getid3_lib::FixedPoint16_16(substr($atom_structure['sample_description_table'][$i]['data'], 24, 4)); 861 $atom_structure['sample_description_table'][$i]['video_data_size'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 28, 4)); 862 $atom_structure['sample_description_table'][$i]['video_frame_count'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 32, 2)); 863 $atom_structure['sample_description_table'][$i]['video_encoder_name_len'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 34, 1)); 864 $atom_structure['sample_description_table'][$i]['video_encoder_name'] = substr($atom_structure['sample_description_table'][$i]['data'], 35, $atom_structure['sample_description_table'][$i]['video_encoder_name_len']); 865 $atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 66, 2)); 866 $atom_structure['sample_description_table'][$i]['video_color_table_id'] = getid3_lib::BigEndian2Int(substr($atom_structure['sample_description_table'][$i]['data'], 68, 2)); 867 868 $atom_structure['sample_description_table'][$i]['video_pixel_color_type'] = (($atom_structure['sample_description_table'][$i]['video_pixel_color_depth'] > 32) ? 'grayscale' : 'color'); 869 $atom_structure['sample_description_table'][$i]['video_pixel_color_name'] = $this->QuicktimeColorNameLookup($atom_structure['sample_description_table'][$i]['video_pixel_color_depth']); 870 871 if ($atom_structure['sample_description_table'][$i]['video_pixel_color_name'] != 'invalid') { 872 $info['quicktime']['video']['codec_fourcc'] = $atom_structure['sample_description_table'][$i]['data_format']; 873 $info['quicktime']['video']['codec_fourcc_lookup'] = $this->QuicktimeVideoCodecLookup($atom_structure['sample_description_table'][$i]['data_format']); 874 $info['quicktime']['video']['codec'] = (($atom_structure['sample_description_table'][$i]['video_encoder_name_len'] > 0) ? $atom_structure['sample_description_table'][$i]['video_encoder_name'] : $atom_structure['sample_description_table'][$i]['data_format']); 875 $info['quicktime']['video']['color_depth'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_depth']; 876 $info['quicktime']['video']['color_depth_name'] = $atom_structure['sample_description_table'][$i]['video_pixel_color_name']; 877 878 $info['video']['codec'] = $info['quicktime']['video']['codec']; 879 $info['video']['bits_per_sample'] = $info['quicktime']['video']['color_depth']; 880 } 881 $info['video']['lossless'] = false; 882 $info['video']['pixel_aspect_ratio'] = (float) 1; 883 break; 884 } 644 $atom_structure['data'] = substr($atom_data, 12); 885 645 break; 886 646 } 887 switch (strtolower($atom_structure['sample_description_table'][$i]['data_format'])) { 888 case 'mp4a': 889 $info['audio']['dataformat'] = 'mp4'; 890 $info['quicktime']['audio']['codec'] = 'mp4'; 891 break; 892 893 case '3ivx': 894 case '3iv1': 895 case '3iv2': 896 $info['video']['dataformat'] = '3ivx'; 897 break; 898 899 case 'xvid': 900 $info['video']['dataformat'] = 'xvid'; 901 break; 902 903 case 'mp4v': 904 $info['video']['dataformat'] = 'mpeg4'; 905 break; 906 907 case 'divx': 908 case 'div1': 909 case 'div2': 910 case 'div3': 911 case 'div4': 912 case 'div5': 913 case 'div6': 914 $info['video']['dataformat'] = 'divx'; 915 break; 916 917 default: 918 // do nothing 919 break; 920 } 921 unset($atom_structure['sample_description_table'][$i]['data']); 922 } 923 break; 924 925 926 case 'stts': // Sample Table Time-to-Sample atom 927 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 928 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 929 $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 930 $sttsEntriesDataOffset = 8; 931 //$FrameRateCalculatorArray = array(); 932 $frames_count = 0; 933 934 $max_stts_entries_to_scan = ($info['php_memory_limit'] ? min(floor($this->getid3->memory_limit / 10000), $atom_structure['number_entries']) : $atom_structure['number_entries']); 935 if ($max_stts_entries_to_scan < $atom_structure['number_entries']) { 936 $this->warning('QuickTime atom "stts" has '.$atom_structure['number_entries'].' but only scanning the first '.$max_stts_entries_to_scan.' entries due to limited PHP memory available ('.floor($atom_structure['number_entries'] / 1048576).'MB).'); 937 } 938 for ($i = 0; $i < $max_stts_entries_to_scan; $i++) { 939 $atom_structure['time_to_sample_table'][$i]['sample_count'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); 940 $sttsEntriesDataOffset += 4; 941 $atom_structure['time_to_sample_table'][$i]['sample_duration'] = getid3_lib::BigEndian2Int(substr($atom_data, $sttsEntriesDataOffset, 4)); 942 $sttsEntriesDataOffset += 4; 943 944 $frames_count += $atom_structure['time_to_sample_table'][$i]['sample_count']; 945 946 // THIS SECTION REPLACED WITH CODE IN "stbl" ATOM 947 //if (!empty($info['quicktime']['time_scale']) && ($atom_structure['time_to_sample_table'][$i]['sample_duration'] > 0)) { 948 // $stts_new_framerate = $info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration']; 949 // if ($stts_new_framerate <= 60) { 950 // // some atoms have durations of "1" giving a very large framerate, which probably is not right 951 // $info['video']['frame_rate'] = max($info['video']['frame_rate'], $stts_new_framerate); 952 // } 953 //} 954 // 955 //$FrameRateCalculatorArray[($info['quicktime']['time_scale'] / $atom_structure['time_to_sample_table'][$i]['sample_duration'])] += $atom_structure['time_to_sample_table'][$i]['sample_count']; 956 } 957 $info['quicktime']['stts_framecount'][] = $frames_count; 958 //$sttsFramesTotal = 0; 959 //$sttsSecondsTotal = 0; 960 //foreach ($FrameRateCalculatorArray as $frames_per_second => $frame_count) { 961 // if (($frames_per_second > 60) || ($frames_per_second < 1)) { 962 // // not video FPS information, probably audio information 963 // $sttsFramesTotal = 0; 964 // $sttsSecondsTotal = 0; 965 // break; 966 // } 967 // $sttsFramesTotal += $frame_count; 968 // $sttsSecondsTotal += $frame_count / $frames_per_second; 969 //} 970 //if (($sttsFramesTotal > 0) && ($sttsSecondsTotal > 0)) { 971 // if (($sttsFramesTotal / $sttsSecondsTotal) > $info['video']['frame_rate']) { 972 // $info['video']['frame_rate'] = $sttsFramesTotal / $sttsSecondsTotal; 973 // } 974 //} 975 break; 976 977 978 case 'stss': // Sample Table Sync Sample (key frames) atom 979 if ($ParseAllPossibleAtoms) { 647 break; 648 649 650 case 'rmqu': // Reference Movie QUality atom 651 $atom_structure['movie_quality'] = getid3_lib::BigEndian2Int($atom_data); 652 break; 653 654 655 case 'rmcs': // Reference Movie Cpu Speed atom 656 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 657 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 658 $atom_structure['cpu_speed_rating'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); 659 break; 660 661 662 case 'rmvc': // Reference Movie Version Check atom 663 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 664 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 665 $atom_structure['gestalt_selector'] = substr($atom_data, 4, 4); 666 $atom_structure['gestalt_value_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 8, 4)); 667 $atom_structure['gestalt_value'] = getid3_lib::BigEndian2Int(substr($atom_data, 12, 4)); 668 $atom_structure['gestalt_check_type'] = getid3_lib::BigEndian2Int(substr($atom_data, 14, 2)); 669 break; 670 671 672 case 'rmcd': // Reference Movie Component check atom 673 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 674 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 675 $atom_structure['component_type'] = substr($atom_data, 4, 4); 676 $atom_structure['component_subtype'] = substr($atom_data, 8, 4); 677 $atom_structure['component_manufacturer'] = substr($atom_data, 12, 4); 678 $atom_structure['component_flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 16, 4)); 679 $atom_structure['component_flags_mask'] = getid3_lib::BigEndian2Int(substr($atom_data, 20, 4)); 680 $atom_structure['component_min_version'] = getid3_lib::BigEndian2Int(substr($atom_data, 24, 4)); 681 break; 682 683 684 case 'rmdr': // Reference Movie Data Rate atom 685 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 686 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 687 $atom_structure['data_rate'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 688 689 $atom_structure['data_rate_bps'] = $atom_structure['data_rate'] * 10; 690 break; 691 692 693 case 'rmla': // Reference Movie Language Atom 694 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 695 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 696 $atom_structure['language_id'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); 697 698 $atom_structure['language'] = $this->QuicktimeLanguageLookup($atom_structure['language_id']); 699 if (empty($info['comments']['language']) || (!in_array($atom_structure['language'], $info['comments']['language']))) { 700 $info['comments']['language'][] = $atom_structure['language']; 701 } 702 break; 703 704 705 case 'ptv ': // Print To Video - defines a movie's full screen mode 706 // http://developer.apple.com/documentation/QuickTime/APIREF/SOURCESIV/at_ptv-_pg.htm 707 $atom_structure['display_size_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 2)); 708 $atom_structure['reserved_1'] = getid3_lib::BigEndian2Int(substr($atom_data, 2, 2)); // hardcoded: 0x0000 709 $atom_structure['reserved_2'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 2)); // hardcoded: 0x0000 710 $atom_structure['slide_show_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 6, 1)); 711 $atom_structure['play_on_open_flag'] = getid3_lib::BigEndian2Int(substr($atom_data, 7, 1)); 712 713 $atom_structure['flags']['play_on_open'] = (bool) $atom_structure['play_on_open_flag']; 714 $atom_structure['flags']['slide_show'] = (bool) $atom_structure['slide_show_flag']; 715 716 $ptv_lookup[0] = 'normal'; 717 $ptv_lookup[1] = 'double'; 718 $ptv_lookup[2] = 'half'; 719 $ptv_lookup[3] = 'full'; 720 $ptv_lookup[4] = 'current'; 721 if (isset($ptv_lookup[$atom_structure['display_size_raw']])) { 722 $atom_structure['display_size'] = $ptv_lookup[$atom_structure['display_size_raw']]; 723 } else { 724 $this->warning('unknown "ptv " display constant ('.$atom_structure['display_size_raw'].')'); 725 } 726 break; 727 728 729 case 'stsd': // Sample Table Sample Description atom 980 730 $atom_structure['version'] = getid3_lib::BigEndian2Int(substr($atom_data, 0, 1)); 981 731 $atom_structure['flags_raw'] = getid3_lib::BigEndian2Int(substr($atom_data, 1, 3)); // hardcoded: 0x0000 982 732 $atom_structure['number_entries'] = getid3_lib::BigEndian2Int(substr($atom_data, 4, 4)); 983 $stssEntriesDataOffset = 8; 733 734 // see: https://github.com/JamesHeinrich/getID3/issues/111 735 // Some corrupt files have been known to have high bits set in the number_entries field 736 // This field shouldn't really need to be 32-bits, values stores are likely in the range 1-100000 737 // Workaround: mask off the upper byte and throw a warning if it's nonzero 738 if ($atom_structure['number_entries'] > 0x000FFFFF) { 739 if ($atom_structure['number_entries'] > 0x00FFFFFF) { 740 $this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Ignoring upper byte and interpreting this as 0x'.getid3_lib::PrintHexBytes(substr($atom_data, 5, 3), true, false).' = '.($atom_structure['number_entries'] & 0x00FFFFFF)); 741 $atom_structure['number_entries'] = ($atom_structure['number_entries'] & 0x00FFFFFF); 742 } else { 743 $this->warning('"stsd" atom contains improbably large number_entries (0x'.getid3_lib::PrintHexBytes(substr($atom_data, 4, 4), true, false).' = '.$atom_structure['number_entries'].'), probably in error. Please report this to info@getid3.org referencing bug report #111'); 744 } 745 } 746 747 $stsdEntriesDataOffset = 8; 984 748 for ($i = 0; $i < $atom_structure['number_entries']; $i++) { 985 $atom_structure['time_to_sample_table'][$i] = getid3_lib::BigEndian2Int(substr($atom_data, $stssEntriesDataOffset, 4)); 986 $stssEntriesDataOffset += 4;