240 } |
240 } |
241 |
241 |
242 /** |
242 /** |
243 * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic |
243 * ANSI/IEEE Standard 754-1985, Standard for Binary Floating Point Arithmetic |
244 * |
244 * |
245 * @link http://www.psc.edu/general/software/packages/ieee/ieee.html |
245 * @link https://web.archive.org/web/20120325162206/http://www.psc.edu/general/software/packages/ieee/ieee.php |
246 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html |
246 * @link http://www.scri.fsu.edu/~jac/MAD3401/Backgrnd/ieee.html |
247 * |
247 * |
248 * @param string $byteword |
248 * @param string $byteword |
249 * |
249 * |
250 * @return float|false |
250 * @return float|false |
292 $exponent = self::Bin2Dec($exponentstring); |
292 $exponent = self::Bin2Dec($exponentstring); |
293 $fraction = self::Bin2Dec($fractionstring); |
293 $fraction = self::Bin2Dec($fractionstring); |
294 |
294 |
295 if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) { |
295 if (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction != 0)) { |
296 // Not a Number |
296 // Not a Number |
297 $floatvalue = false; |
297 $floatvalue = NAN; |
298 } elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) { |
298 } elseif (($exponent == (pow(2, $exponentbits) - 1)) && ($fraction == 0)) { |
299 if ($signbit == '1') { |
299 if ($signbit == '1') { |
300 $floatvalue = '-infinity'; |
300 $floatvalue = -INF; |
301 } else { |
301 } else { |
302 $floatvalue = '+infinity'; |
302 $floatvalue = INF; |
303 } |
303 } |
304 } elseif (($exponent == 0) && ($fraction == 0)) { |
304 } elseif (($exponent == 0) && ($fraction == 0)) { |
305 if ($signbit == '1') { |
305 if ($signbit == '1') { |
306 $floatvalue = -0; |
306 $floatvalue = -0; |
307 } else { |
307 } else { |
425 * @param int $number |
425 * @param int $number |
426 * |
426 * |
427 * @return string |
427 * @return string |
428 */ |
428 */ |
429 public static function Dec2Bin($number) { |
429 public static function Dec2Bin($number) { |
|
430 if (!is_numeric($number)) { |
|
431 // https://github.com/JamesHeinrich/getID3/issues/299 |
|
432 trigger_error('TypeError: Dec2Bin(): Argument #1 ($number) must be numeric, '.gettype($number).' given', E_USER_WARNING); |
|
433 return ''; |
|
434 } |
|
435 $bytes = array(); |
430 while ($number >= 256) { |
436 while ($number >= 256) { |
431 $bytes[] = (($number / 256) - (floor($number / 256))) * 256; |
437 $bytes[] = (int) (($number / 256) - (floor($number / 256))) * 256; |
432 $number = floor($number / 256); |
438 $number = floor($number / 256); |
433 } |
439 } |
434 $bytes[] = $number; |
440 $bytes[] = (int) $number; |
435 $binstring = ''; |
441 $binstring = ''; |
436 for ($i = 0; $i < count($bytes); $i++) { |
442 foreach ($bytes as $i => $byte) { |
437 $binstring = (($i == count($bytes) - 1) ? decbin($bytes[$i]) : str_pad(decbin($bytes[$i]), 8, '0', STR_PAD_LEFT)).$binstring; |
443 $binstring = (($i == count($bytes) - 1) ? decbin($byte) : str_pad(decbin($byte), 8, '0', STR_PAD_LEFT)).$binstring; |
438 } |
444 } |
439 return $binstring; |
445 return $binstring; |
440 } |
446 } |
441 |
447 |
442 /** |
448 /** |
663 // is the same as: |
669 // is the same as: |
664 // $foo = array('path'=>array('to'=>'array('my'=>array('file.txt')))); |
670 // $foo = array('path'=>array('to'=>'array('my'=>array('file.txt')))); |
665 // or |
671 // or |
666 // $foo['path']['to']['my'] = 'file.txt'; |
672 // $foo['path']['to']['my'] = 'file.txt'; |
667 $ArrayPath = ltrim($ArrayPath, $Separator); |
673 $ArrayPath = ltrim($ArrayPath, $Separator); |
|
674 $ReturnedArray = array(); |
668 if (($pos = strpos($ArrayPath, $Separator)) !== false) { |
675 if (($pos = strpos($ArrayPath, $Separator)) !== false) { |
669 $ReturnedArray[substr($ArrayPath, 0, $pos)] = self::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value); |
676 $ReturnedArray[substr($ArrayPath, 0, $pos)] = self::CreateDeepArray(substr($ArrayPath, $pos + 1), $Separator, $Value); |
670 } else { |
677 } else { |
671 $ReturnedArray[$ArrayPath] = $Value; |
678 $ReturnedArray[$ArrayPath] = $Value; |
672 } |
679 } |
1536 * @return bool |
1543 * @return bool |
1537 */ |
1544 */ |
1538 public static function CopyTagsToComments(&$ThisFileInfo, $option_tags_html=true) { |
1545 public static function CopyTagsToComments(&$ThisFileInfo, $option_tags_html=true) { |
1539 // Copy all entries from ['tags'] into common ['comments'] |
1546 // Copy all entries from ['tags'] into common ['comments'] |
1540 if (!empty($ThisFileInfo['tags'])) { |
1547 if (!empty($ThisFileInfo['tags'])) { |
1541 if (isset($ThisFileInfo['tags']['id3v1'])) { |
1548 |
1542 // bubble ID3v1 to the end, if present to aid in detecting bad ID3v1 encodings |
1549 // Some tag types can only support limited character sets and may contain data in non-standard encoding (usually ID3v1) |
1543 $ID3v1 = $ThisFileInfo['tags']['id3v1']; |
1550 // and/or poorly-transliterated tag values that are also in tag formats that do support full-range character sets |
1544 unset($ThisFileInfo['tags']['id3v1']); |
1551 // To make the output more user-friendly, process the potentially-problematic tag formats last to enhance the chance that |
1545 $ThisFileInfo['tags']['id3v1'] = $ID3v1; |
1552 // the first entries in [comments] are the most correct and the "bad" ones (if any) come later. |
1546 unset($ID3v1); |
1553 // https://github.com/JamesHeinrich/getID3/issues/338 |
|
1554 $processLastTagTypes = array('id3v1','riff'); |
|
1555 foreach ($processLastTagTypes as $processLastTagType) { |
|
1556 if (isset($ThisFileInfo['tags'][$processLastTagType])) { |
|
1557 // bubble ID3v1 to the end, if present to aid in detecting bad ID3v1 encodings |
|
1558 $temp = $ThisFileInfo['tags'][$processLastTagType]; |
|
1559 unset($ThisFileInfo['tags'][$processLastTagType]); |
|
1560 $ThisFileInfo['tags'][$processLastTagType] = $temp; |
|
1561 unset($temp); |
|
1562 } |
1547 } |
1563 } |
1548 foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) { |
1564 foreach ($ThisFileInfo['tags'] as $tagtype => $tagarray) { |
1549 foreach ($tagarray as $tagname => $tagdata) { |
1565 foreach ($tagarray as $tagname => $tagdata) { |
1550 foreach ($tagdata as $key => $value) { |
1566 foreach ($tagdata as $key => $value) { |
1551 if (!empty($value)) { |
1567 if (!empty($value)) { |
1560 $oldvaluelength = strlen(trim($existingvalue)); |
1576 $oldvaluelength = strlen(trim($existingvalue)); |
1561 if (($newvaluelength <= $oldvaluelength) && (substr($existingvalue, 0, $newvaluelength) == trim($value))) { |
1577 if (($newvaluelength <= $oldvaluelength) && (substr($existingvalue, 0, $newvaluelength) == trim($value))) { |
1562 // new value is identical but shorter-than (or equal-length to) one already in comments - skip |
1578 // new value is identical but shorter-than (or equal-length to) one already in comments - skip |
1563 break 2; |
1579 break 2; |
1564 } |
1580 } |
1565 } |
1581 |
1566 if (function_exists('mb_convert_encoding')) { |
1582 if (function_exists('mb_convert_encoding')) { |
1567 if (trim($value) == trim(substr(mb_convert_encoding($existingvalue, $ThisFileInfo['id3v1']['encoding'], $ThisFileInfo['encoding']), 0, 30))) { |
1583 if (trim($value) == trim(substr(mb_convert_encoding($existingvalue, $ThisFileInfo['id3v1']['encoding'], $ThisFileInfo['encoding']), 0, 30))) { |
1568 // value stored in ID3v1 appears to be probably the multibyte value transliterated (badly) into ISO-8859-1 in ID3v1. |
1584 // value stored in ID3v1 appears to be probably the multibyte value transliterated (badly) into ISO-8859-1 in ID3v1. |
1569 // As an example, Foobar2000 will do this if you tag a file with Chinese or Arabic or Cyrillic or something that doesn't fit into ISO-8859-1 the ID3v1 will consist of mostly "?" characters, one per multibyte unrepresentable character |
1585 // As an example, Foobar2000 will do this if you tag a file with Chinese or Arabic or Cyrillic or something that doesn't fit into ISO-8859-1 the ID3v1 will consist of mostly "?" characters, one per multibyte unrepresentable character |
1570 break 2; |
1586 break 2; |
|
1587 } |
1571 } |
1588 } |
1572 } |
1589 } |
1573 |
1590 |
1574 } elseif (!is_array($value)) { |
1591 } elseif (!is_array($value)) { |
1575 |
1592 |
1576 $newvaluelength = strlen(trim($value)); |
1593 $newvaluelength = strlen(trim($value)); |
|
1594 $newvaluelengthMB = mb_strlen(trim($value)); |
1577 foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) { |
1595 foreach ($ThisFileInfo['comments'][$tagname] as $existingkey => $existingvalue) { |
1578 $oldvaluelength = strlen(trim($existingvalue)); |
1596 $oldvaluelength = strlen(trim($existingvalue)); |
|
1597 $oldvaluelengthMB = mb_strlen(trim($existingvalue)); |
|
1598 if (($newvaluelengthMB == $oldvaluelengthMB) && ($existingvalue == getid3_lib::iconv_fallback('UTF-8', 'ASCII', $value))) { |
|
1599 // https://github.com/JamesHeinrich/getID3/issues/338 |
|
1600 // check for tags containing extended characters that may have been forced into limited-character storage (e.g. UTF8 values into ASCII) |
|
1601 // which will usually display unrepresentable characters as "?" |
|
1602 $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value); |
|
1603 break; |
|
1604 } |
1579 if ((strlen($existingvalue) > 10) && ($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) { |
1605 if ((strlen($existingvalue) > 10) && ($newvaluelength > $oldvaluelength) && (substr(trim($value), 0, strlen($existingvalue)) == $existingvalue)) { |
1580 $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value); |
1606 $ThisFileInfo['comments'][$tagname][$existingkey] = trim($value); |
1581 break; |
1607 break; |
1582 } |
1608 } |
1583 } |
1609 } |
1599 } |
1625 } |
1600 } |
1626 } |
1601 } |
1627 } |
1602 |
1628 |
1603 // attempt to standardize spelling of returned keys |
1629 // attempt to standardize spelling of returned keys |
1604 $StandardizeFieldNames = array( |
1630 if (!empty($ThisFileInfo['comments'])) { |
1605 'tracknumber' => 'track_number', |
1631 $StandardizeFieldNames = array( |
1606 'track' => 'track_number', |
1632 'tracknumber' => 'track_number', |
1607 ); |
1633 'track' => 'track_number', |
1608 foreach ($StandardizeFieldNames as $badkey => $goodkey) { |
1634 ); |
1609 if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) { |
1635 foreach ($StandardizeFieldNames as $badkey => $goodkey) { |
1610 $ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey]; |
1636 if (array_key_exists($badkey, $ThisFileInfo['comments']) && !array_key_exists($goodkey, $ThisFileInfo['comments'])) { |
1611 unset($ThisFileInfo['comments'][$badkey]); |
1637 $ThisFileInfo['comments'][$goodkey] = $ThisFileInfo['comments'][$badkey]; |
|
1638 unset($ThisFileInfo['comments'][$badkey]); |
|
1639 } |
1612 } |
1640 } |
1613 } |
1641 } |
1614 |
1642 |
1615 if ($option_tags_html) { |
1643 if ($option_tags_html) { |
1616 // Copy ['comments'] to ['comments_html'] |
1644 // Copy ['comments'] to ['comments_html'] |
1732 * @param string $path |
1760 * @param string $path |
1733 * |
1761 * |
1734 * @return float|bool |
1762 * @return float|bool |
1735 */ |
1763 */ |
1736 public static function getFileSizeSyscall($path) { |
1764 public static function getFileSizeSyscall($path) { |
|
1765 $commandline = null; |
1737 $filesize = false; |
1766 $filesize = false; |
1738 |
1767 |
1739 if (GETID3_OS_ISWINDOWS) { |
1768 if (GETID3_OS_ISWINDOWS) { |
1740 if (class_exists('COM')) { // From PHP 5.3.15 and 5.4.5, COM and DOTNET is no longer built into the php core.you have to add COM support in php.ini: |
1769 if (class_exists('COM')) { // From PHP 5.3.15 and 5.4.5, COM and DOTNET is no longer built into the php core.you have to add COM support in php.ini: |
1741 $filesystem = new COM('Scripting.FileSystemObject'); |
1770 $filesystem = new COM('Scripting.FileSystemObject'); |
1793 * @param string $path A path. |
1822 * @param string $path A path. |
1794 * @param string $suffix If the name component ends in suffix this will also be cut off. |
1823 * @param string $suffix If the name component ends in suffix this will also be cut off. |
1795 * |
1824 * |
1796 * @return string |
1825 * @return string |
1797 */ |
1826 */ |
1798 public static function mb_basename($path, $suffix = null) { |
1827 public static function mb_basename($path, $suffix = '') { |
1799 $splited = preg_split('#/#', rtrim($path, '/ ')); |
1828 $splited = preg_split('#/#', rtrim($path, '/ ')); |
1800 return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1); |
1829 return substr(basename('X'.$splited[count($splited) - 1], $suffix), 1); |
1801 } |
1830 } |
1802 |
1831 |
1803 } |
1832 } |