547 $info = &$this->getid3->info;
548 $id3v2_majorversion =
$info[
'id3v2'][
'majorversion'];
551 if (empty($parsedFrame[
'framenamelong'])) {
552 unset($parsedFrame[
'framenamelong']);
555 if (empty($parsedFrame[
'framenameshort'])) {
556 unset($parsedFrame[
'framenameshort']);
559 if ($id3v2_majorversion >= 3) {
560 if ($id3v2_majorversion == 3) {
563 $parsedFrame[
'flags'][
'TagAlterPreservation'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x8000);
564 $parsedFrame[
'flags'][
'FileAlterPreservation'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x4000);
565 $parsedFrame[
'flags'][
'ReadOnly'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x2000);
566 $parsedFrame[
'flags'][
'compression'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x0080);
567 $parsedFrame[
'flags'][
'Encryption'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x0040);
568 $parsedFrame[
'flags'][
'GroupingIdentity'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x0020);
570 } elseif ($id3v2_majorversion == 4) {
573 $parsedFrame[
'flags'][
'TagAlterPreservation'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x4000);
574 $parsedFrame[
'flags'][
'FileAlterPreservation'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x2000);
575 $parsedFrame[
'flags'][
'ReadOnly'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x1000);
576 $parsedFrame[
'flags'][
'GroupingIdentity'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x0040);
577 $parsedFrame[
'flags'][
'compression'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x0008);
578 $parsedFrame[
'flags'][
'Encryption'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x0004);
579 $parsedFrame[
'flags'][
'Unsynchronisation'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x0002);
580 $parsedFrame[
'flags'][
'DataLengthIndicator'] = (bool) ($parsedFrame[
'frame_flags_raw'] & 0x0001);
583 if ($parsedFrame[
'flags'][
'Unsynchronisation']) {
587 if ($parsedFrame[
'flags'][
'DataLengthIndicator']) {
589 $parsedFrame[
'data'] = substr($parsedFrame[
'data'], 4);
594 if ($parsedFrame[
'flags'][
'compression']) {
596 if (!function_exists(
'gzuncompress')) {
597 $this->
warning(
'gzuncompress() support required to decompress ID3v2 frame "'.$parsedFrame[
'frame_name'].
'"');
599 if ($decompresseddata = @gzuncompress(substr($parsedFrame[
'data'], 4))) {
601 $parsedFrame[
'data'] = $decompresseddata;
602 unset($decompresseddata);
604 $this->
warning(
'gzuncompress() failed on compressed contents of ID3v2 frame "'.$parsedFrame[
'frame_name'].
'"');
610 if (!empty($parsedFrame[
'flags'][
'DataLengthIndicator'])) {
611 if ($parsedFrame[
'data_length_indicator'] != strlen($parsedFrame[
'data'])) {
612 $this->
warning(
'ID3v2 frame "'.$parsedFrame[
'frame_name'].
'" should be '.$parsedFrame[
'data_length_indicator'].
' bytes long according to DataLengthIndicator, but found '.strlen($parsedFrame[
'data']).
' bytes of data');
616 if (isset($parsedFrame[
'datalength']) && ($parsedFrame[
'datalength'] == 0)) {
618 $warning =
'Frame "'.$parsedFrame[
'frame_name'].
'" at offset '.$parsedFrame[
'dataoffset'].
' has no data portion';
619 switch ($parsedFrame[
'frame_name']) {
621 $warning .=
' (this is known to happen with files tagged by RioPort)';
629 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'UFID')) ||
630 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'UFI'))) {
636 $exploded = explode(
"\x00", $parsedFrame[
'data'], 2);
637 $parsedFrame[
'ownerid'] = (isset($exploded[0]) ? $exploded[0] :
'');
638 $parsedFrame[
'data'] = (isset($exploded[1]) ? $exploded[1] :
'');
640 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'TXXX')) ||
641 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'TXX'))) {
650 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
652 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
653 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
654 $frame_textencoding_terminator =
"\x00";
656 $frame_terminatorpos = strpos($parsedFrame[
'data'], $frame_textencoding_terminator, $frame_offset);
657 if (ord(substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
658 $frame_terminatorpos++;
660 $frame_description = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
661 if (in_array($frame_description,
array(
"\x00",
"\x00\x00",
"\xFF\xFE",
"\xFE\xFF"))) {
663 $frame_description =
'';
665 $parsedFrame[
'encodingid'] = $frame_textencoding;
669 $parsedFrame[
'data'] = substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
670 if (!empty($parsedFrame[
'framenameshort']) && !empty($parsedFrame[
'data'])) {
671 $commentkey = ($parsedFrame[
'description'] ? $parsedFrame[
'description'] : (isset(
$info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']]) ? count(
$info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']]) : 0));
672 if (!isset(
$info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']]) || !array_key_exists($commentkey,
$info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']])) {
673 $info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']][$commentkey] = trim(
getid3_lib::iconv_fallback($parsedFrame[
'encoding'],
$info[
'id3v2'][
'encoding'], $parsedFrame[
'data']));
681 } elseif ($parsedFrame[
'frame_name']{0} ==
'T') {
689 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
690 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
691 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
694 $parsedFrame[
'data'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
696 $parsedFrame[
'encodingid'] = $frame_textencoding;
699 if (!empty($parsedFrame[
'framenameshort']) && !empty($parsedFrame[
'data'])) {
704 switch ($parsedFrame[
'encoding']) {
716 $Txxx_elements =
array();
717 $Txxx_elements_start_offset = 0;
718 for (
$i = 0;
$i < strlen($parsedFrame[
'data']);
$i += $wordsize) {
719 if (substr($parsedFrame[
'data'],
$i, $wordsize) == str_repeat(
"\x00", $wordsize)) {
720 $Txxx_elements[] = substr($parsedFrame[
'data'], $Txxx_elements_start_offset,
$i - $Txxx_elements_start_offset);
721 $Txxx_elements_start_offset =
$i + $wordsize;
724 $Txxx_elements[] = substr($parsedFrame[
'data'], $Txxx_elements_start_offset,
$i - $Txxx_elements_start_offset);
725 foreach ($Txxx_elements as $Txxx_element) {
727 if (!empty($string)) {
728 $info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']][] = $string;
731 unset($string, $wordsize,
$i, $Txxx_elements, $Txxx_element, $Txxx_elements_start_offset);
734 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'WXXX')) ||
735 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'WXX'))) {
744 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
746 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
747 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
748 $frame_textencoding_terminator =
"\x00";
750 $frame_terminatorpos = strpos($parsedFrame[
'data'], $frame_textencoding_terminator, $frame_offset);
751 if (ord(substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
752 $frame_terminatorpos++;
754 $frame_description = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
755 if (in_array($frame_description,
array(
"\x00",
"\x00\x00",
"\xFF\xFE",
"\xFE\xFF"))) {
757 $frame_description =
'';
759 $parsedFrame[
'data'] = substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
761 $frame_terminatorpos = strpos($parsedFrame[
'data'], $frame_textencoding_terminator);
762 if (ord(substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
763 $frame_terminatorpos++;
765 if ($frame_terminatorpos) {
768 $frame_urldata = (
string) substr($parsedFrame[
'data'], 0, $frame_terminatorpos);
771 $frame_urldata = (
string) $parsedFrame[
'data'];
774 $parsedFrame[
'encodingid'] = $frame_textencoding;
777 $parsedFrame[
'url'] = $frame_urldata;
778 $parsedFrame[
'description'] = $frame_description;
779 if (!empty($parsedFrame[
'framenameshort']) && $parsedFrame[
'url']) {
782 unset($parsedFrame[
'data']);
785 } elseif ($parsedFrame[
'frame_name']{0} ==
'W') {
792 $parsedFrame[
'url'] = trim($parsedFrame[
'data']);
793 if (!empty($parsedFrame[
'framenameshort']) && $parsedFrame[
'url']) {
794 $info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']][] = $parsedFrame[
'url'];
796 unset($parsedFrame[
'data']);
799 } elseif ((($id3v2_majorversion == 3) && ($parsedFrame[
'frame_name'] ==
'IPLS')) ||
800 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'IPL'))) {
808 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
809 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
810 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
812 $parsedFrame[
'encodingid'] = $frame_textencoding;
814 $parsedFrame[
'data_raw'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
819 $IPLS_parts =
array();
820 if (strpos($parsedFrame[
'data_raw'],
"\x00") !==
false) {
821 $IPLS_parts_unsorted =
array();
822 if (((strlen($parsedFrame[
'data_raw']) % 2) == 0) && ((substr($parsedFrame[
'data_raw'], 0, 2) ==
"\xFF\xFE") || (substr($parsedFrame[
'data_raw'], 0, 2) ==
"\xFE\xFF"))) {
825 for (
$i = 0;
$i < strlen($parsedFrame[
'data_raw']);
$i += 2) {
826 $twobytes = substr($parsedFrame[
'data_raw'],
$i, 2);
827 if ($twobytes ===
"\x00\x00") {
831 $thisILPS .= $twobytes;
834 if (strlen($thisILPS) > 2) {
839 $IPLS_parts_unsorted = explode(
"\x00", $parsedFrame[
'data_raw']);
841 if (count($IPLS_parts_unsorted) == 1) {
843 foreach ($IPLS_parts_unsorted as
$key => $value) {
844 $IPLS_parts_sorted = preg_split(
'#[;,\\r\\n\\t]#', $value);
846 foreach ($IPLS_parts_sorted as $person) {
847 $IPLS_parts[] =
array(
'position'=>$position,
'person'=>$person);
850 } elseif ((count($IPLS_parts_unsorted) % 2) == 0) {
853 foreach ($IPLS_parts_unsorted as
$key => $value) {
854 if ((
$key % 2) == 0) {
858 $IPLS_parts[] =
array(
'position'=>$position,
'person'=>$person);
864 foreach ($IPLS_parts_unsorted as
$key => $value) {
865 $IPLS_parts[] =
array($value);
870 $IPLS_parts = preg_split(
'#[;,\\r\\n\\t]#', $parsedFrame[
'data_raw']);
872 $parsedFrame[
'data'] = $IPLS_parts;
874 if (!empty($parsedFrame[
'framenameshort']) && !empty($parsedFrame[
'data'])) {
875 $info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']][] = $parsedFrame[
'data'];
879 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'MCDI')) ||
880 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'MCI'))) {
885 if (!empty($parsedFrame[
'framenameshort']) && !empty($parsedFrame[
'data'])) {
886 $info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']][] = $parsedFrame[
'data'];
890 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'ETCO')) ||
891 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'ETC'))) {
905 $parsedFrame[
'timestampformat'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
907 while ($frame_offset < strlen($parsedFrame[
'data'])) {
908 $parsedFrame[
'typeid'] = substr($parsedFrame[
'data'], $frame_offset++, 1);
913 unset($parsedFrame[
'data']);
916 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'MLLT')) ||
917 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'MLL'))) {
935 $parsedFrame[
'data'] = substr($parsedFrame[
'data'], 10);
936 while ($frame_offset < strlen($parsedFrame[
'data'])) {
939 $reference_counter = 0;
940 while (strlen($deviationbitstream) > 0) {
941 $parsedFrame[$reference_counter][
'bytedeviation'] = bindec(substr($deviationbitstream, 0, $parsedFrame[
'bitsforbytesdeviation']));
942 $parsedFrame[$reference_counter][
'msdeviation'] = bindec(substr($deviationbitstream, $parsedFrame[
'bitsforbytesdeviation'], $parsedFrame[
'bitsformsdeviation']));
943 $deviationbitstream = substr($deviationbitstream, $parsedFrame[
'bitsforbytesdeviation'] + $parsedFrame[
'bitsformsdeviation']);
944 $reference_counter++;
946 unset($parsedFrame[
'data']);
949 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'SYTC')) ||
950 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'STC'))) {
960 $parsedFrame[
'timestampformat'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
961 $timestamp_counter = 0;
962 while ($frame_offset < strlen($parsedFrame[
'data'])) {
963 $parsedFrame[$timestamp_counter][
'tempo'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
964 if ($parsedFrame[$timestamp_counter][
'tempo'] == 255) {
965 $parsedFrame[$timestamp_counter][
'tempo'] += ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
967 $parsedFrame[$timestamp_counter][
'timestamp'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, 4));
969 $timestamp_counter++;
971 unset($parsedFrame[
'data']);
974 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'USLT')) ||
975 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'ULT'))) {
985 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
987 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
988 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
989 $frame_textencoding_terminator =
"\x00";
991 $frame_language = substr($parsedFrame[
'data'], $frame_offset, 3);
993 $frame_terminatorpos = strpos($parsedFrame[
'data'], $frame_textencoding_terminator, $frame_offset);
994 if (ord(substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
995 $frame_terminatorpos++;
997 $frame_description = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
998 if (in_array($frame_description,
array(
"\x00",
"\x00\x00",
"\xFF\xFE",
"\xFE\xFF"))) {
1000 $frame_description =
'';
1002 $parsedFrame[
'data'] = substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
1004 $parsedFrame[
'encodingid'] = $frame_textencoding;
1007 $parsedFrame[
'language'] = $frame_language;
1008 $parsedFrame[
'languagename'] = $this->
LanguageLookup($frame_language,
false);
1009 $parsedFrame[
'description'] = $frame_description;
1010 if (!empty($parsedFrame[
'framenameshort']) && !empty($parsedFrame[
'data'])) {
1013 unset($parsedFrame[
'data']);
1016 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'SYLT')) ||
1017 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'SLT'))) {
1033 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1035 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
1036 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
1037 $frame_textencoding_terminator =
"\x00";
1039 $frame_language = substr($parsedFrame[
'data'], $frame_offset, 3);
1041 $parsedFrame[
'timestampformat'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1042 $parsedFrame[
'contenttypeid'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1044 $parsedFrame[
'encodingid'] = $frame_textencoding;
1047 $parsedFrame[
'language'] = $frame_language;
1048 $parsedFrame[
'languagename'] = $this->
LanguageLookup($frame_language,
false);
1050 $timestampindex = 0;
1051 $frame_remainingdata = substr($parsedFrame[
'data'], $frame_offset);
1052 while (strlen($frame_remainingdata)) {
1054 $frame_terminatorpos = strpos($frame_remainingdata, $frame_textencoding_terminator);
1055 if ($frame_terminatorpos ===
false) {
1056 $frame_remainingdata =
'';
1058 if (ord(substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
1059 $frame_terminatorpos++;
1061 $parsedFrame[
'lyrics'][$timestampindex][
'data'] = substr($frame_remainingdata, $frame_offset, $frame_terminatorpos - $frame_offset);
1063 $frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator));
1064 if (($timestampindex == 0) && (ord($frame_remainingdata{0}) != 0)) {
1068 $frame_remainingdata = substr($frame_remainingdata, 4);
1073 unset($parsedFrame[
'data']);
1076 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'COMM')) ||
1077 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'COM'))) {
1086 if (strlen($parsedFrame[
'data']) < 5) {
1088 $this->
warning(
'Invalid data (too short) for "'.$parsedFrame[
'frame_name'].
'" frame at offset '.$parsedFrame[
'dataoffset']);
1093 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1095 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
1096 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
1097 $frame_textencoding_terminator =
"\x00";
1099 $frame_language = substr($parsedFrame[
'data'], $frame_offset, 3);
1101 $frame_terminatorpos = strpos($parsedFrame[
'data'], $frame_textencoding_terminator, $frame_offset);
1102 if (ord(substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
1103 $frame_terminatorpos++;
1105 $frame_description = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1106 if (in_array($frame_description,
array(
"\x00",
"\x00\x00",
"\xFF\xFE",
"\xFE\xFF"))) {
1108 $frame_description =
'';
1110 $frame_text = (
string) substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
1112 $parsedFrame[
'encodingid'] = $frame_textencoding;
1115 $parsedFrame[
'language'] = $frame_language;
1116 $parsedFrame[
'languagename'] = $this->
LanguageLookup($frame_language,
false);
1117 $parsedFrame[
'description'] = $frame_description;
1118 $parsedFrame[
'data'] = $frame_text;
1119 if (!empty($parsedFrame[
'framenameshort']) && !empty($parsedFrame[
'data'])) {
1120 $commentkey = ($parsedFrame[
'description'] ? $parsedFrame[
'description'] : (!empty(
$info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']]) ? count(
$info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']]) : 0));
1121 if (!isset(
$info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']]) || !array_key_exists($commentkey,
$info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']])) {
1122 $info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']][$commentkey] =
getid3_lib::iconv_fallback($parsedFrame[
'encoding'],
$info[
'id3v2'][
'encoding'], $parsedFrame[
'data']);
1130 } elseif (($id3v2_majorversion >= 4) && ($parsedFrame[
'frame_name'] ==
'RVA2')) {
1143 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00");
1144 $frame_idstring = substr($parsedFrame[
'data'], 0, $frame_terminatorpos);
1145 if (ord($frame_idstring) === 0) {
1146 $frame_idstring =
'';
1148 $frame_remainingdata = substr($parsedFrame[
'data'], $frame_terminatorpos + strlen(
"\x00"));
1149 $parsedFrame[
'description'] = $frame_idstring;
1150 $RVA2channelcounter = 0;
1151 while (strlen($frame_remainingdata) >= 5) {
1153 $frame_channeltypeid = ord(substr($frame_remainingdata, $frame_offset++, 1));
1154 $parsedFrame[$RVA2channelcounter][
'channeltypeid'] = $frame_channeltypeid;
1155 $parsedFrame[$RVA2channelcounter][
'channeltype'] = $this->
RVA2ChannelTypeLookup($frame_channeltypeid);
1156 $parsedFrame[$RVA2channelcounter][
'volumeadjust'] =
getid3_lib::BigEndian2Int(substr($frame_remainingdata, $frame_offset, 2),
false,
true);
1158 $parsedFrame[$RVA2channelcounter][
'bitspeakvolume'] = ord(substr($frame_remainingdata, $frame_offset++, 1));
1159 if (($parsedFrame[$RVA2channelcounter][
'bitspeakvolume'] < 1) || ($parsedFrame[$RVA2channelcounter][
'bitspeakvolume'] > 4)) {
1160 $this->
warning(
'ID3v2::RVA2 frame['.$RVA2channelcounter.
'] contains invalid '.$parsedFrame[$RVA2channelcounter][
'bitspeakvolume'].
'-byte bits-representing-peak value');
1163 $frame_bytespeakvolume = ceil($parsedFrame[$RVA2channelcounter][
'bitspeakvolume'] / 8);
1164 $parsedFrame[$RVA2channelcounter][
'peakvolume'] =
getid3_lib::BigEndian2Int(substr($frame_remainingdata, $frame_offset, $frame_bytespeakvolume));
1165 $frame_remainingdata = substr($frame_remainingdata, $frame_offset + $frame_bytespeakvolume);
1166 $RVA2channelcounter++;
1168 unset($parsedFrame[
'data']);
1171 } elseif ((($id3v2_majorversion == 3) && ($parsedFrame[
'frame_name'] ==
'RVAD')) ||
1172 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'RVA'))) {
1196 $parsedFrame[
'incdec'][
'right'] = (bool) substr($frame_incrdecrflags, 6, 1);
1197 $parsedFrame[
'incdec'][
'left'] = (bool) substr($frame_incrdecrflags, 7, 1);
1198 $parsedFrame[
'bitsvolume'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1199 $frame_bytesvolume = ceil($parsedFrame[
'bitsvolume'] / 8);
1200 $parsedFrame[
'volumechange'][
'right'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1201 if ($parsedFrame[
'incdec'][
'right'] ===
false) {
1202 $parsedFrame[
'volumechange'][
'right'] *= -1;
1204 $frame_offset += $frame_bytesvolume;
1205 $parsedFrame[
'volumechange'][
'left'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1206 if ($parsedFrame[
'incdec'][
'left'] ===
false) {
1207 $parsedFrame[
'volumechange'][
'left'] *= -1;
1209 $frame_offset += $frame_bytesvolume;
1210 $parsedFrame[
'peakvolume'][
'right'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1211 $frame_offset += $frame_bytesvolume;
1212 $parsedFrame[
'peakvolume'][
'left'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1213 $frame_offset += $frame_bytesvolume;
1214 if ($id3v2_majorversion == 3) {
1215 $parsedFrame[
'data'] = substr($parsedFrame[
'data'], $frame_offset);
1216 if (strlen($parsedFrame[
'data']) > 0) {
1217 $parsedFrame[
'incdec'][
'rightrear'] = (bool) substr($frame_incrdecrflags, 4, 1);
1218 $parsedFrame[
'incdec'][
'leftrear'] = (bool) substr($frame_incrdecrflags, 5, 1);
1219 $parsedFrame[
'volumechange'][
'rightrear'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1220 if ($parsedFrame[
'incdec'][
'rightrear'] ===
false) {
1221 $parsedFrame[
'volumechange'][
'rightrear'] *= -1;
1223 $frame_offset += $frame_bytesvolume;
1224 $parsedFrame[
'volumechange'][
'leftrear'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1225 if ($parsedFrame[
'incdec'][
'leftrear'] ===
false) {
1226 $parsedFrame[
'volumechange'][
'leftrear'] *= -1;
1228 $frame_offset += $frame_bytesvolume;
1229 $parsedFrame[
'peakvolume'][
'rightrear'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1230 $frame_offset += $frame_bytesvolume;
1231 $parsedFrame[
'peakvolume'][
'leftrear'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1232 $frame_offset += $frame_bytesvolume;
1234 $parsedFrame[
'data'] = substr($parsedFrame[
'data'], $frame_offset);
1235 if (strlen($parsedFrame[
'data']) > 0) {
1236 $parsedFrame[
'incdec'][
'center'] = (bool) substr($frame_incrdecrflags, 3, 1);
1237 $parsedFrame[
'volumechange'][
'center'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1238 if ($parsedFrame[
'incdec'][
'center'] ===
false) {
1239 $parsedFrame[
'volumechange'][
'center'] *= -1;
1241 $frame_offset += $frame_bytesvolume;
1242 $parsedFrame[
'peakvolume'][
'center'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1243 $frame_offset += $frame_bytesvolume;
1245 $parsedFrame[
'data'] = substr($parsedFrame[
'data'], $frame_offset);
1246 if (strlen($parsedFrame[
'data']) > 0) {
1247 $parsedFrame[
'incdec'][
'bass'] = (bool) substr($frame_incrdecrflags, 2, 1);
1248 $parsedFrame[
'volumechange'][
'bass'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1249 if ($parsedFrame[
'incdec'][
'bass'] ===
false) {
1250 $parsedFrame[
'volumechange'][
'bass'] *= -1;
1252 $frame_offset += $frame_bytesvolume;
1253 $parsedFrame[
'peakvolume'][
'bass'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1254 $frame_offset += $frame_bytesvolume;
1257 unset($parsedFrame[
'data']);
1260 } elseif (($id3v2_majorversion >= 4) && ($parsedFrame[
'frame_name'] ==
'EQU2')) {
1273 $frame_interpolationmethod = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1274 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1275 $frame_idstring = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1276 if (ord($frame_idstring) === 0) {
1277 $frame_idstring =
'';
1279 $parsedFrame[
'description'] = $frame_idstring;
1280 $frame_remainingdata = substr($parsedFrame[
'data'], $frame_terminatorpos + strlen(
"\x00"));
1281 while (strlen($frame_remainingdata)) {
1284 $frame_remainingdata = substr($frame_remainingdata, 4);
1286 $parsedFrame[
'interpolationmethod'] = $frame_interpolationmethod;
1287 unset($parsedFrame[
'data']);
1290 } elseif ((($id3v2_majorversion == 3) && ($parsedFrame[
'frame_name'] ==
'EQUA')) ||
1291 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'EQU'))) {
1303 $parsedFrame[
'adjustmentbits'] = substr($parsedFrame[
'data'], $frame_offset++, 1);
1304 $frame_adjustmentbytes = ceil($parsedFrame[
'adjustmentbits'] / 8);
1306 $frame_remainingdata = (
string) substr($parsedFrame[
'data'], $frame_offset);
1307 while (strlen($frame_remainingdata) > 0) {
1309 $frame_incdec = (bool) substr($frame_frequencystr, 0, 1);
1310 $frame_frequency = bindec(substr($frame_frequencystr, 1, 15));
1311 $parsedFrame[$frame_frequency][
'incdec'] = $frame_incdec;
1312 $parsedFrame[$frame_frequency][
'adjustment'] =
getid3_lib::BigEndian2Int(substr($frame_remainingdata, 2, $frame_adjustmentbytes));
1313 if ($parsedFrame[$frame_frequency][
'incdec'] ===
false) {
1314 $parsedFrame[$frame_frequency][
'adjustment'] *= -1;
1316 $frame_remainingdata = substr($frame_remainingdata, 2 + $frame_adjustmentbytes);
1318 unset($parsedFrame[
'data']);
1321 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'RVRB')) ||
1322 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'REV'))) {
1341 $parsedFrame[
'bouncesL'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1342 $parsedFrame[
'bouncesR'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1343 $parsedFrame[
'feedbackLL'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1344 $parsedFrame[
'feedbackLR'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1345 $parsedFrame[
'feedbackRR'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1346 $parsedFrame[
'feedbackRL'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1347 $parsedFrame[
'premixLR'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1348 $parsedFrame[
'premixRL'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1349 unset($parsedFrame[
'data']);
1352 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'APIC')) ||
1353 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'PIC'))) {
1366 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1368 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
1369 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
1370 $frame_textencoding_terminator =
"\x00";
1373 if ($id3v2_majorversion == 2 && strlen($parsedFrame[
'data']) > $frame_offset) {
1374 $frame_imagetype = substr($parsedFrame[
'data'], $frame_offset, 3);
1375 if (strtolower($frame_imagetype) ==
'ima') {
1378 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1379 $frame_mimetype = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1380 if (ord($frame_mimetype) === 0) {
1381 $frame_mimetype =
'';
1383 $frame_imagetype = strtoupper(str_replace(
'image/',
'', strtolower($frame_mimetype)));
1384 if ($frame_imagetype ==
'JPEG') {
1385 $frame_imagetype =
'JPG';
1387 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1392 if ($id3v2_majorversion > 2 && strlen($parsedFrame[
'data']) > $frame_offset) {
1393 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1394 $frame_mimetype = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1395 if (ord($frame_mimetype) === 0) {
1396 $frame_mimetype =
'';
1398 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1401 $frame_picturetype = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1403 if ($frame_offset >= $parsedFrame[
'datalength']) {
1404 $this->
warning(
'data portion of APIC frame is missing at offset '.($parsedFrame[
'dataoffset'] + 8 + $frame_offset));
1406 $frame_terminatorpos = strpos($parsedFrame[
'data'], $frame_textencoding_terminator, $frame_offset);
1407 if (ord(substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
1408 $frame_terminatorpos++;
1410 $frame_description = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1411 if (in_array($frame_description,
array(
"\x00",
"\x00\x00",
"\xFF\xFE",
"\xFE\xFF"))) {
1413 $frame_description =
'';
1415 $parsedFrame[
'encodingid'] = $frame_textencoding;
1418 if ($id3v2_majorversion == 2) {
1419 $parsedFrame[
'imagetype'] = $frame_imagetype;
1421 $parsedFrame[
'mime'] = $frame_mimetype;
1423 $parsedFrame[
'picturetypeid'] = $frame_picturetype;
1425 $parsedFrame[
'description'] = $frame_description;
1426 $parsedFrame[
'data'] = substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
1427 $parsedFrame[
'datalength'] = strlen($parsedFrame[
'data']);
1429 $parsedFrame[
'image_mime'] =
'';
1430 $imageinfo =
array();
1432 if (($imagechunkcheck[2] >= 1) && ($imagechunkcheck[2] <= 3)) {
1433 $parsedFrame[
'image_mime'] =
'image/'.getid3_lib::ImageTypesLookup($imagechunkcheck[2]);
1434 if ($imagechunkcheck[0]) {
1435 $parsedFrame[
'image_width'] = $imagechunkcheck[0];
1437 if ($imagechunkcheck[1]) {
1438 $parsedFrame[
'image_height'] = $imagechunkcheck[1];
1444 if ($this->getid3->option_save_attachments ===
false) {
1446 unset($parsedFrame[
'data']);
1449 if ($this->getid3->option_save_attachments ===
true) {
1460 } elseif (is_string($this->getid3->option_save_attachments)) {
1461 $dir = rtrim(str_replace(
array(
'/',
'\\'), DIRECTORY_SEPARATOR, $this->getid3->option_save_attachments), DIRECTORY_SEPARATOR);
1462 if (!is_dir($dir) || !is_writable($dir)) {
1464 $this->
warning(
'attachment at '.$frame_offset.
' cannot be saved to "'.$dir.
'" (not writable)');
1465 unset($parsedFrame[
'data']);
1470 if (is_string($this->getid3->option_save_attachments)) {
1471 $destination_filename = $dir.DIRECTORY_SEPARATOR.md5(
$info[
'filenamepath']).
'_'.$frame_offset;
1472 if (!file_exists($destination_filename) || is_writable($destination_filename)) {
1473 file_put_contents($destination_filename, $parsedFrame[
'data']);
1475 $this->
warning(
'attachment at '.$frame_offset.
' cannot be saved to "'.$destination_filename.
'" (not writable)');
1477 $parsedFrame[
'data_filename'] = $destination_filename;
1478 unset($parsedFrame[
'data']);
1480 if (!empty($parsedFrame[
'framenameshort']) && !empty($parsedFrame[
'data'])) {
1481 if (!isset(
$info[
'id3v2'][
'comments'][
'picture'])) {
1482 $info[
'id3v2'][
'comments'][
'picture'] =
array();
1484 $comments_picture_data =
array();
1485 foreach (
array(
'data',
'image_mime',
'image_width',
'image_height',
'imagetype',
'picturetype',
'description',
'datalength') as $picture_key) {
1486 if (isset($parsedFrame[$picture_key])) {
1487 $comments_picture_data[$picture_key] = $parsedFrame[$picture_key];
1490 $info[
'id3v2'][
'comments'][
'picture'][] = $comments_picture_data;
1491 unset($comments_picture_data);
1497 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'GEOB')) ||
1498 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'GEO'))) {
1509 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1511 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
1512 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
1513 $frame_textencoding_terminator =
"\x00";
1515 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1516 $frame_mimetype = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1517 if (ord($frame_mimetype) === 0) {
1518 $frame_mimetype =
'';
1520 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1522 $frame_terminatorpos = strpos($parsedFrame[
'data'], $frame_textencoding_terminator, $frame_offset);
1523 if (ord(substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
1524 $frame_terminatorpos++;
1526 $frame_filename = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1527 if (ord($frame_filename) === 0) {
1528 $frame_filename =
'';
1530 $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
1532 $frame_terminatorpos = strpos($parsedFrame[
'data'], $frame_textencoding_terminator, $frame_offset);
1533 if (ord(substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
1534 $frame_terminatorpos++;
1536 $frame_description = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1537 if (in_array($frame_description,
array(
"\x00",
"\x00\x00",
"\xFF\xFE",
"\xFE\xFF"))) {
1539 $frame_description =
'';
1541 $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
1543 $parsedFrame[
'objectdata'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
1544 $parsedFrame[
'encodingid'] = $frame_textencoding;
1547 $parsedFrame[
'mime'] = $frame_mimetype;
1548 $parsedFrame[
'filename'] = $frame_filename;
1549 $parsedFrame[
'description'] = $frame_description;
1550 unset($parsedFrame[
'data']);
1553 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'PCNT')) ||
1554 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'CNT'))) {
1564 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'POPM')) ||
1565 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'POP'))) {
1574 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1575 $frame_emailaddress = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1576 if (ord($frame_emailaddress) === 0) {
1577 $frame_emailaddress =
'';
1579 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1580 $frame_rating = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1582 $parsedFrame[
'email'] = $frame_emailaddress;
1583 $parsedFrame[
'rating'] = $frame_rating;
1584 unset($parsedFrame[
'data']);
1587 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'RBUF')) ||
1588 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'BUF'))) {
1600 $parsedFrame[
'flags'][
'embededinfo'] = (bool) substr($frame_embeddedinfoflags, 7, 1);
1602 unset($parsedFrame[
'data']);
1605 } elseif (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'CRM')) {
1614 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1615 $frame_ownerid = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1616 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1618 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1619 $frame_description = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1620 if (in_array($frame_description,
array(
"\x00",
"\x00\x00",
"\xFF\xFE",
"\xFE\xFF"))) {
1622 $frame_description =
'';
1624 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1626 $parsedFrame[
'ownerid'] = $frame_ownerid;
1627 $parsedFrame[
'data'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
1628 $parsedFrame[
'description'] = $frame_description;
1629 unset($parsedFrame[
'data']);
1632 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'AENC')) ||
1633 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'CRA'))) {
1643 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1644 $frame_ownerid = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1645 if (ord($frame_ownerid) === 0) {
1646 $frame_ownerid =
'';
1648 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1649 $parsedFrame[
'ownerid'] = $frame_ownerid;
1654 $parsedFrame[
'encryptioninfo'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
1655 unset($parsedFrame[
'data']);
1658 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'LINK')) ||
1659 (($id3v2_majorversion == 2) && ($parsedFrame[
'frame_name'] ==
'LNK'))) {
1669 if ($id3v2_majorversion == 2) {
1670 $parsedFrame[
'frameid'] = substr($parsedFrame[
'data'], $frame_offset, 3);
1673 $parsedFrame[
'frameid'] = substr($parsedFrame[
'data'], $frame_offset, 4);
1677 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1678 $frame_url = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1679 if (ord($frame_url) === 0) {
1682 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1683 $parsedFrame[
'url'] = $frame_url;
1685 $parsedFrame[
'additionaldata'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
1686 if (!empty($parsedFrame[
'framenameshort']) && $parsedFrame[
'url']) {
1689 unset($parsedFrame[
'data']);
1692 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'POSS')) {
1699 $parsedFrame[
'timestampformat'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1701 unset($parsedFrame[
'data']);
1704 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'USER')) {
1713 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1714 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
1715 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
1717 $frame_language = substr($parsedFrame[
'data'], $frame_offset, 3);
1719 $parsedFrame[
'language'] = $frame_language;
1720 $parsedFrame[
'languagename'] = $this->
LanguageLookup($frame_language,
false);
1721 $parsedFrame[
'encodingid'] = $frame_textencoding;
1724 $parsedFrame[
'data'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
1725 if (!empty($parsedFrame[
'framenameshort']) && !empty($parsedFrame[
'data'])) {
1728 unset($parsedFrame[
'data']);
1731 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'OWNE')) {
1740 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1741 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
1742 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
1744 $parsedFrame[
'encodingid'] = $frame_textencoding;
1747 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1748 $frame_pricepaid = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1749 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1751 $parsedFrame[
'pricepaid'][
'currencyid'] = substr($frame_pricepaid, 0, 3);
1752 $parsedFrame[
'pricepaid'][
'currency'] = $this->
LookupCurrencyUnits($parsedFrame[
'pricepaid'][
'currencyid']);
1753 $parsedFrame[
'pricepaid'][
'value'] = substr($frame_pricepaid, 3);
1755 $parsedFrame[
'purchasedate'] = substr($parsedFrame[
'data'], $frame_offset, 8);
1757 $parsedFrame[
'purchasedateunix'] = mktime (0, 0, 0, substr($parsedFrame[
'purchasedate'], 4, 2), substr($parsedFrame[
'purchasedate'], 6, 2), substr($parsedFrame[
'purchasedate'], 0, 4));
1761 $parsedFrame[
'seller'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
1762 unset($parsedFrame[
'data']);
1765 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'COMR')) {
1780 $frame_textencoding = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1782 if ((($id3v2_majorversion <= 3) && ($frame_textencoding > 1)) || (($id3v2_majorversion == 4) && ($frame_textencoding > 3))) {
1783 $this->
warning(
'Invalid text encoding byte ('.$frame_textencoding.
') in frame "'.$parsedFrame[
'frame_name'].
'" - defaulting to ISO-8859-1 encoding');
1784 $frame_textencoding_terminator =
"\x00";
1787 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1788 $frame_pricestring = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1789 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1790 $frame_rawpricearray = explode(
'/', $frame_pricestring);
1791 foreach ($frame_rawpricearray as
$key => $val) {
1792 $frame_currencyid = substr($val, 0, 3);
1793 $parsedFrame[
'price'][$frame_currencyid][
'currency'] = $this->
LookupCurrencyUnits($frame_currencyid);
1794 $parsedFrame[
'price'][$frame_currencyid][
'value'] = substr($val, 3);
1797 $frame_datestring = substr($parsedFrame[
'data'], $frame_offset, 8);
1800 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1801 $frame_contacturl = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1802 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1804 $frame_receivedasid = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1806 $frame_terminatorpos = strpos($parsedFrame[
'data'], $frame_textencoding_terminator, $frame_offset);
1807 if (ord(substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
1808 $frame_terminatorpos++;
1810 $frame_sellername = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1811 if (ord($frame_sellername) === 0) {
1812 $frame_sellername =
'';
1814 $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
1816 $frame_terminatorpos = strpos($parsedFrame[
'data'], $frame_textencoding_terminator, $frame_offset);
1817 if (ord(substr($parsedFrame[
'data'], $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
1818 $frame_terminatorpos++;
1820 $frame_description = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1821 if (in_array($frame_description,
array(
"\x00",
"\x00\x00",
"\xFF\xFE",
"\xFE\xFF"))) {
1823 $frame_description =
'';
1825 $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
1827 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1828 $frame_mimetype = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1829 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1831 $frame_sellerlogo = substr($parsedFrame[
'data'], $frame_offset);
1833 $parsedFrame[
'encodingid'] = $frame_textencoding;
1836 $parsedFrame[
'pricevaliduntil'] = $frame_datestring;
1837 $parsedFrame[
'contacturl'] = $frame_contacturl;
1838 $parsedFrame[
'receivedasid'] = $frame_receivedasid;
1840 $parsedFrame[
'sellername'] = $frame_sellername;
1841 $parsedFrame[
'description'] = $frame_description;
1842 $parsedFrame[
'mime'] = $frame_mimetype;
1843 $parsedFrame[
'logo'] = $frame_sellerlogo;
1844 unset($parsedFrame[
'data']);
1847 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'ENCR')) {
1857 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1858 $frame_ownerid = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1859 if (ord($frame_ownerid) === 0) {
1860 $frame_ownerid =
'';
1862 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1864 $parsedFrame[
'ownerid'] = $frame_ownerid;
1865 $parsedFrame[
'methodsymbol'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1866 $parsedFrame[
'data'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
1869 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'GRID')) {
1880 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1881 $frame_ownerid = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1882 if (ord($frame_ownerid) === 0) {
1883 $frame_ownerid =
'';
1885 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1887 $parsedFrame[
'ownerid'] = $frame_ownerid;
1888 $parsedFrame[
'groupsymbol'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1889 $parsedFrame[
'data'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
1892 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'PRIV')) {
1900 $frame_terminatorpos = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
1901 $frame_ownerid = substr($parsedFrame[
'data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1902 if (ord($frame_ownerid) === 0) {
1903 $frame_ownerid =
'';
1905 $frame_offset = $frame_terminatorpos + strlen(
"\x00");
1907 $parsedFrame[
'ownerid'] = $frame_ownerid;
1908 $parsedFrame[
'data'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
1911 } elseif (($id3v2_majorversion >= 4) && ($parsedFrame[
'frame_name'] ==
'SIGN')) {
1919 $parsedFrame[
'groupsymbol'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1920 $parsedFrame[
'data'] = (
string) substr($parsedFrame[
'data'], $frame_offset);
1923 } elseif (($id3v2_majorversion >= 4) && ($parsedFrame[
'frame_name'] ==
'SEEK')) {
1932 } elseif (($id3v2_majorversion >= 4) && ($parsedFrame[
'frame_name'] ==
'ASPI')) {
1949 $parsedFrame[
'bitsperpoint'] = ord(substr($parsedFrame[
'data'], $frame_offset++, 1));
1950 $frame_bytesperpoint = ceil($parsedFrame[
'bitsperpoint'] / 8);
1951 for (
$i = 0;
$i < $parsedFrame[
'indexpoints'];
$i++) {
1953 $frame_offset += $frame_bytesperpoint;
1955 unset($parsedFrame[
'data']);
1957 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'RGAD')) {
1972 $rg_track_adjustment =
getid3_lib::Dec2Bin(substr($parsedFrame[
'data'], $frame_offset, 2));
1974 $rg_album_adjustment =
getid3_lib::Dec2Bin(substr($parsedFrame[
'data'], $frame_offset, 2));
1976 $parsedFrame[
'raw'][
'track'][
'name'] =
getid3_lib::Bin2Dec(substr($rg_track_adjustment, 0, 3));
1977 $parsedFrame[
'raw'][
'track'][
'originator'] =
getid3_lib::Bin2Dec(substr($rg_track_adjustment, 3, 3));
1978 $parsedFrame[
'raw'][
'track'][
'signbit'] =
getid3_lib::Bin2Dec(substr($rg_track_adjustment, 6, 1));
1979 $parsedFrame[
'raw'][
'track'][
'adjustment'] =
getid3_lib::Bin2Dec(substr($rg_track_adjustment, 7, 9));
1980 $parsedFrame[
'raw'][
'album'][
'name'] =
getid3_lib::Bin2Dec(substr($rg_album_adjustment, 0, 3));
1981 $parsedFrame[
'raw'][
'album'][
'originator'] =
getid3_lib::Bin2Dec(substr($rg_album_adjustment, 3, 3));
1982 $parsedFrame[
'raw'][
'album'][
'signbit'] =
getid3_lib::Bin2Dec(substr($rg_album_adjustment, 6, 1));
1983 $parsedFrame[
'raw'][
'album'][
'adjustment'] =
getid3_lib::Bin2Dec(substr($rg_album_adjustment, 7, 9));
1986 $parsedFrame[
'track'][
'adjustment'] =
getid3_lib::RGADadjustmentLookup($parsedFrame[
'raw'][
'track'][
'adjustment'], $parsedFrame[
'raw'][
'track'][
'signbit']);
1989 $parsedFrame[
'album'][
'adjustment'] =
getid3_lib::RGADadjustmentLookup($parsedFrame[
'raw'][
'album'][
'adjustment'], $parsedFrame[
'raw'][
'album'][
'signbit']);
1991 $info[
'replay_gain'][
'track'][
'peak'] = $parsedFrame[
'peakamplitude'];
1992 $info[
'replay_gain'][
'track'][
'originator'] = $parsedFrame[
'track'][
'originator'];
1993 $info[
'replay_gain'][
'track'][
'adjustment'] = $parsedFrame[
'track'][
'adjustment'];
1994 $info[
'replay_gain'][
'album'][
'originator'] = $parsedFrame[
'album'][
'originator'];
1995 $info[
'replay_gain'][
'album'][
'adjustment'] = $parsedFrame[
'album'][
'adjustment'];
1997 unset($parsedFrame[
'data']);
1999 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'CHAP')) {
2010 @list($parsedFrame[
'element_id']) = explode(
"\x00", $parsedFrame[
'data'], 2);
2011 $frame_offset += strlen($parsedFrame[
'element_id'].
"\x00");
2016 if (substr($parsedFrame[
'data'], $frame_offset, 4) !=
"\xFF\xFF\xFF\xFF") {
2021 if (substr($parsedFrame[
'data'], $frame_offset, 4) !=
"\xFF\xFF\xFF\xFF") {
2027 if ($frame_offset < strlen($parsedFrame[
'data'])) {
2028 $parsedFrame[
'subframes'] =
array();
2029 while ($frame_offset < strlen($parsedFrame[
'data'])) {
2031 $subframe =
array();
2032 $subframe[
'name'] = substr($parsedFrame[
'data'], $frame_offset, 4);
2038 if ($subframe[
'size'] > (strlen($parsedFrame[
'data']) - $frame_offset)) {
2039 $this->
warning(
'CHAP subframe "'.$subframe[
'name'].
'" at frame offset '.$frame_offset.
' claims to be "'.$subframe[
'size'].
'" bytes, which is more than the available data ('.(strlen($parsedFrame[
'data']) - $frame_offset).
' bytes)');
2042 $subframe_rawdata = substr($parsedFrame[
'data'], $frame_offset, $subframe[
'size']);
2043 $frame_offset += $subframe[
'size'];
2045 $subframe[
'encodingid'] = ord(substr($subframe_rawdata, 0, 1));
2046 $subframe[
'text'] = substr($subframe_rawdata, 1);
2049 switch (substr($encoding_converted_text, 0, 2)) {
2052 switch (strtoupper(
$info[
'id3v2'][
'encoding'])) {
2055 $encoding_converted_text = substr($encoding_converted_text, 2);
2068 if (($subframe[
'name'] ==
'TIT2') || ($subframe[
'name'] ==
'TIT3')) {
2069 if ($subframe[
'name'] ==
'TIT2') {
2070 $parsedFrame[
'chapter_name'] = $encoding_converted_text;
2071 } elseif ($subframe[
'name'] ==
'TIT3') {
2072 $parsedFrame[
'chapter_description'] = $encoding_converted_text;
2074 $parsedFrame[
'subframes'][] = $subframe;
2076 $this->
warning(
'ID3v2.CHAP subframe "'.$subframe[
'name'].
'" not handled (only TIT2 and TIT3)');
2079 unset($subframe_rawdata, $subframe, $encoding_converted_text);
2082 $id3v2_chapter_entry =
array();
2083 foreach (
array(
'id',
'time_begin',
'time_end',
'offset_begin',
'offset_end',
'chapter_name',
'chapter_description') as $id3v2_chapter_key) {
2084 if (isset($parsedFrame[$id3v2_chapter_key])) {
2085 $id3v2_chapter_entry[$id3v2_chapter_key] = $parsedFrame[$id3v2_chapter_key];
2088 if (!isset(
$info[
'id3v2'][
'chapters'])) {
2091 $info[
'id3v2'][
'chapters'][] = $id3v2_chapter_entry;
2092 unset($id3v2_chapter_entry, $id3v2_chapter_key);
2095 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame[
'frame_name'] ==
'CTOC')) {
2105 @list($parsedFrame[
'element_id']) = explode(
"\x00", $parsedFrame[
'data'], 2);
2106 $frame_offset += strlen($parsedFrame[
'element_id'].
"\x00");
2107 $ctoc_flags_raw = ord(substr($parsedFrame[
'data'], $frame_offset, 1));
2109 $parsedFrame[
'entry_count'] = ord(substr($parsedFrame[
'data'], $frame_offset, 1));
2112 $terminator_position = null;
2113 for (
$i = 0;
$i < $parsedFrame[
'entry_count'];
$i++) {
2114 $terminator_position = strpos($parsedFrame[
'data'],
"\x00", $frame_offset);
2115 $parsedFrame[
'child_element_ids'][
$i] = substr($parsedFrame[
'data'], $frame_offset, $terminator_position - $frame_offset);
2116 $frame_offset = $terminator_position + 1;
2119 $parsedFrame[
'ctoc_flags'][
'ordered'] = (bool) ($ctoc_flags_raw & 0x01);
2120 $parsedFrame[
'ctoc_flags'][
'top_level'] = (bool) ($ctoc_flags_raw & 0x03);
2122 unset($ctoc_flags_raw, $terminator_position);
2124 if ($frame_offset < strlen($parsedFrame[
'data'])) {
2125 $parsedFrame[
'subframes'] =
array();
2126 while ($frame_offset < strlen($parsedFrame[
'data'])) {
2128 $subframe =
array();
2129 $subframe[
'name'] = substr($parsedFrame[
'data'], $frame_offset, 4);
2135 if ($subframe[
'size'] > (strlen($parsedFrame[
'data']) - $frame_offset)) {
2136 $this->
warning(
'CTOS subframe "'.$subframe[
'name'].
'" at frame offset '.$frame_offset.
' claims to be "'.$subframe[
'size'].
'" bytes, which is more than the available data ('.(strlen($parsedFrame[
'data']) - $frame_offset).
' bytes)');
2139 $subframe_rawdata = substr($parsedFrame[
'data'], $frame_offset, $subframe[
'size']);
2140 $frame_offset += $subframe[
'size'];
2142 $subframe[
'encodingid'] = ord(substr($subframe_rawdata, 0, 1));
2143 $subframe[
'text'] = substr($subframe_rawdata, 1);
2146 switch (substr($encoding_converted_text, 0, 2)) {
2149 switch (strtoupper(
$info[
'id3v2'][
'encoding'])) {
2152 $encoding_converted_text = substr($encoding_converted_text, 2);
2165 if (($subframe[
'name'] ==
'TIT2') || ($subframe[
'name'] ==
'TIT3')) {
2166 if ($subframe[
'name'] ==
'TIT2') {
2167 $parsedFrame[
'toc_name'] = $encoding_converted_text;
2168 } elseif ($subframe[
'name'] ==
'TIT3') {
2169 $parsedFrame[
'toc_description'] = $encoding_converted_text;
2171 $parsedFrame[
'subframes'][] = $subframe;
2173 $this->
warning(
'ID3v2.CTOC subframe "'.$subframe[
'name'].
'" not handled (only TIT2 and TIT3)');
2176 unset($subframe_rawdata, $subframe, $encoding_converted_text);
LookupCurrencyUnits($currencyid)
static RGADnameLookup($namecode)
static RGADoriginatorLookup($originatorcode)
static Bin2Dec($binstring, $signed=false)
static LanguageLookup($languagecode, $casesensitive=false)
static iconv_fallback($in_charset, $out_charset, $string)
static BigEndian2Bin($byteword)
static BigEndian2Float($byteword)
static IsValidDateStampString($datestamp)
static FrameNameLongLookup($framename)
static RGADadjustmentLookup($rawadjustment, $signbit)
static TextEncodingNameLookup($encoding)
static APICPictureTypeLookup($index, $returnarray=false)
static RVA2ChannelTypeLookup($index)
static GetDataImageSize($imgData, &$imageinfo=array())
Create styles array
The data for the language used.
static FrameNameShortLookup($framename)
static COMRReceivedAsLookup($index)
static iconv_fallback_iso88591_utf8($string, $bom=false)
static SYTLContentTypeLookup($index)
static BigEndian2Int($byteword, $synchsafe=false, $signed=false)
static TextEncodingTerminatorLookup($encoding)
static ETCOEventLookup($index)