544 {
545
546
547 $info = &$this->getid3->info;
548 $id3v2_majorversion =
$info[
'id3v2'][
'majorversion'];
549
551 if (empty($parsedFrame['framenamelong'])) {
552 unset($parsedFrame['framenamelong']);
553 }
555 if (empty($parsedFrame['framenameshort'])) {
556 unset($parsedFrame['framenameshort']);
557 }
558
559 if ($id3v2_majorversion >= 3) {
560 if ($id3v2_majorversion == 3) {
561
562
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);
569
570 } elseif ($id3v2_majorversion == 4) {
571
572
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);
581
582
583 if ($parsedFrame['flags']['Unsynchronisation']) {
585 }
586
587 if ($parsedFrame['flags']['DataLengthIndicator']) {
589 $parsedFrame['data'] = substr($parsedFrame['data'], 4);
590 }
591 }
592
593
594 if ($parsedFrame['flags']['compression']) {
596 if (!function_exists('gzuncompress')) {
597 $this->
warning(
'gzuncompress() support required to decompress ID3v2 frame "'.$parsedFrame[
'frame_name'].
'"');
598 } else {
599 if ($decompresseddata = @gzuncompress(substr($parsedFrame['data'], 4))) {
600
601 $parsedFrame['data'] = $decompresseddata;
602 unset($decompresseddata);
603 } else {
604 $this->
warning(
'gzuncompress() failed on compressed contents of ID3v2 frame "'.$parsedFrame[
'frame_name'].
'"');
605 }
606 }
607 }
608 }
609
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');
613 }
614 }
615
616 if (isset($parsedFrame['datalength']) && ($parsedFrame['datalength'] == 0)) {
617
618 $warning =
'Frame "'.$parsedFrame[
'frame_name'].
'" at offset '.$parsedFrame[
'dataoffset'].
' has no data portion';
619 switch ($parsedFrame['frame_name']) {
620 case 'WCOM':
621 $warning .=
' (this is known to happen with files tagged by RioPort)';
622 break;
623
624 default:
625 break;
626 }
628
629 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'UFID')) ||
630 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'UFI'))) {
631
632
633
634
635
636 $exploded = explode("\x00", $parsedFrame['data'], 2);
637 $parsedFrame['ownerid'] = (isset($exploded[0]) ? $exploded[0] : '');
638 $parsedFrame['data'] = (isset($exploded[1]) ? $exploded[1] : '');
639
640 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'TXXX')) ||
641 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'TXX'))) {
642
643
644
645
646
647
648
649 $frame_offset = 0;
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";
655 }
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++;
659 }
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"))) {
662
663 $frame_description = '';
664 }
665 $parsedFrame['encodingid'] = $frame_textencoding;
667
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']));
674 } else {
676 }
677 }
678
679
680
681 } elseif ($parsedFrame['frame_name']{0} == 'T') {
682
683
684
685
686
687
688 $frame_offset = 0;
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');
692 }
693
694 $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
695
696 $parsedFrame['encodingid'] = $frame_textencoding;
698
699 if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
700
701
702
703
704 switch ($parsedFrame['encoding']) {
705 case 'UTF-16':
706 case 'UTF-16BE':
707 case 'UTF-16LE':
708 $wordsize = 2;
709 break;
710 case 'ISO-8859-1':
711 case 'UTF-8':
712 default:
713 $wordsize = 1;
714 break;
715 }
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;
722 }
723 }
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;
729 }
730 }
731 unset($string, $wordsize,
$i, $Txxx_elements, $Txxx_element, $Txxx_elements_start_offset);
732 }
733
734 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'WXXX')) ||
735 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'WXX'))) {
736
737
738
739
740
741
742
743 $frame_offset = 0;
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";
749 }
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++;
753 }
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"))) {
756
757 $frame_description = '';
758 }
759 $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
760
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++;
764 }
765 if ($frame_terminatorpos) {
766
767
768 $frame_urldata = (string) substr($parsedFrame['data'], 0, $frame_terminatorpos);
769 } else {
770
771 $frame_urldata = (string) $parsedFrame['data'];
772 }
773
774 $parsedFrame['encodingid'] = $frame_textencoding;
776
777 $parsedFrame['url'] = $frame_urldata;
778 $parsedFrame['description'] = $frame_description;
779 if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
781 }
782 unset($parsedFrame['data']);
783
784
785 } elseif ($parsedFrame['frame_name']{0} == 'W') {
786
787
788
789
790
791
792 $parsedFrame['url'] = trim($parsedFrame['data']);
793 if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
794 $info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']][] = $parsedFrame[
'url'];
795 }
796 unset($parsedFrame['data']);
797
798
799 } elseif ((($id3v2_majorversion == 3) && ($parsedFrame['frame_name'] == 'IPLS')) ||
800 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'IPL'))) {
801
802
803
804
805
806
807 $frame_offset = 0;
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');
811 }
812 $parsedFrame['encodingid'] = $frame_textencoding;
814 $parsedFrame['data_raw'] = (string) substr($parsedFrame['data'], $frame_offset);
815
816
817
818
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"))) {
823
824 $thisILPS = '';
825 for (
$i = 0;
$i < strlen($parsedFrame[
'data_raw']);
$i += 2) {
826 $twobytes = substr($parsedFrame[
'data_raw'],
$i, 2);
827 if ($twobytes === "\x00\x00") {
829 $thisILPS = '';
830 } else {
831 $thisILPS .= $twobytes;
832 }
833 }
834 if (strlen($thisILPS) > 2) {
836 }
837 } else {
838
839 $IPLS_parts_unsorted = explode("\x00", $parsedFrame['data_raw']);
840 }
841 if (count($IPLS_parts_unsorted) == 1) {
842
843 foreach ($IPLS_parts_unsorted as
$key => $value) {
844 $IPLS_parts_sorted = preg_split('#[;,\\r\\n\\t]#', $value);
845 $position = '';
846 foreach ($IPLS_parts_sorted as $person) {
847 $IPLS_parts[] = array('position'=>$position, 'person'=>$person);
848 }
849 }
850 } elseif ((count($IPLS_parts_unsorted) % 2) == 0) {
851 $position = '';
852 $person = '';
853 foreach ($IPLS_parts_unsorted as
$key => $value) {
854 if ((
$key % 2) == 0) {
855 $position = $value;
856 } else {
857 $person = $value;
858 $IPLS_parts[] = array('position'=>$position, 'person'=>$person);
859 $position = '';
860 $person = '';
861 }
862 }
863 } else {
864 foreach ($IPLS_parts_unsorted as
$key => $value) {
865 $IPLS_parts[] = array($value);
866 }
867 }
868
869 } else {
870 $IPLS_parts = preg_split('#[;,\\r\\n\\t]#', $parsedFrame['data_raw']);
871 }
872 $parsedFrame['data'] = $IPLS_parts;
873
874 if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
875 $info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']][] = $parsedFrame[
'data'];
876 }
877
878
879 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'MCDI')) ||
880 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'MCI'))) {
881
882
883
884
885 if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
886 $info[
'id3v2'][
'comments'][$parsedFrame[
'framenameshort']][] = $parsedFrame[
'data'];
887 }
888
889
890 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'ETCO')) ||
891 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'ETC'))) {
892
893
894
895
896
897
898
899
900
901
902
903
904 $frame_offset = 0;
905 $parsedFrame['timestampformat'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
906
907 while ($frame_offset < strlen($parsedFrame['data'])) {
908 $parsedFrame['typeid'] = substr($parsedFrame['data'], $frame_offset++, 1);
911 $frame_offset += 4;
912 }
913 unset($parsedFrame['data']);
914
915
916 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'MLLT')) ||
917 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'MLL'))) {
918
919
920
921
922
923
924
925
926
927
928
929 $frame_offset = 0;
935 $parsedFrame['data'] = substr($parsedFrame['data'], 10);
936 while ($frame_offset < strlen($parsedFrame['data'])) {
938 }
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++;
945 }
946 unset($parsedFrame['data']);
947
948
949 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'SYTC')) ||
950 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'STC'))) {
951
952
953
954
955
956
957
958
959 $frame_offset = 0;
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));
966 }
967 $parsedFrame[$timestamp_counter][
'timestamp'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, 4));
968 $frame_offset += 4;
969 $timestamp_counter++;
970 }
971 unset($parsedFrame['data']);
972
973
974 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'USLT')) ||
975 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'ULT'))) {
976
977
978
979
980
981
982
983
984 $frame_offset = 0;
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";
990 }
991 $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
992 $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++;
996 }
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"))) {
999
1000 $frame_description = '';
1001 }
1002 $parsedFrame['data'] = substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
1003
1004 $parsedFrame['encodingid'] = $frame_textencoding;
1006
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'])) {
1012 }
1013 unset($parsedFrame['data']);
1014
1015
1016 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'SYLT')) ||
1017 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'SLT'))) {
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032 $frame_offset = 0;
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";
1038 }
1039 $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
1040 $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;
1046
1047 $parsedFrame['language'] = $frame_language;
1048 $parsedFrame[
'languagename'] = $this->
LanguageLookup($frame_language,
false);
1049
1050 $timestampindex = 0;
1051 $frame_remainingdata = substr($parsedFrame['data'], $frame_offset);
1052 while (strlen($frame_remainingdata)) {
1053 $frame_offset = 0;
1054 $frame_terminatorpos = strpos($frame_remainingdata, $frame_textencoding_terminator);
1055 if ($frame_terminatorpos === false) {
1056 $frame_remainingdata = '';
1057 } else {
1058 if (ord(substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator), 1)) === 0) {
1059 $frame_terminatorpos++;
1060 }
1061 $parsedFrame['lyrics'][$timestampindex]['data'] = substr($frame_remainingdata, $frame_offset, $frame_terminatorpos - $frame_offset);
1062
1063 $frame_remainingdata = substr($frame_remainingdata, $frame_terminatorpos + strlen($frame_textencoding_terminator));
1064 if (($timestampindex == 0) && (ord($frame_remainingdata{0}) != 0)) {
1065
1066 } else {
1068 $frame_remainingdata = substr($frame_remainingdata, 4);
1069 }
1070 $timestampindex++;
1071 }
1072 }
1073 unset($parsedFrame['data']);
1074
1075
1076 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'COMM')) ||
1077 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'COM'))) {
1078
1079
1080
1081
1082
1083
1084
1085
1086 if (strlen($parsedFrame['data']) < 5) {
1087
1088 $this->
warning(
'Invalid data (too short) for "'.$parsedFrame[
'frame_name'].
'" frame at offset '.$parsedFrame[
'dataoffset']);
1089
1090 } else {
1091
1092 $frame_offset = 0;
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";
1098 }
1099 $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
1100 $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++;
1104 }
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"))) {
1107
1108 $frame_description = '';
1109 }
1110 $frame_text = (string) substr($parsedFrame['data'], $frame_terminatorpos + strlen($frame_textencoding_terminator));
1111
1112 $parsedFrame['encodingid'] = $frame_textencoding;
1114
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']);
1123 } else {
1125 }
1126 }
1127
1128 }
1129
1130 } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'RVA2')) {
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
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 = '';
1147 }
1148 $frame_remainingdata = substr($parsedFrame['data'], $frame_terminatorpos + strlen("\x00"));
1149 $parsedFrame['description'] = $frame_idstring;
1150 $RVA2channelcounter = 0;
1151 while (strlen($frame_remainingdata) >= 5) {
1152 $frame_offset = 0;
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);
1157 $frame_offset += 2;
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');
1161 break;
1162 }
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++;
1167 }
1168 unset($parsedFrame['data']);
1169
1170
1171 } elseif ((($id3v2_majorversion == 3) && ($parsedFrame['frame_name'] == 'RVAD')) ||
1172 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'RVA'))) {
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194 $frame_offset = 0;
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;
1203 }
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;
1208 }
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;
1222 }
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;
1227 }
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;
1233 }
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;
1240 }
1241 $frame_offset += $frame_bytesvolume;
1242 $parsedFrame[
'peakvolume'][
'center'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1243 $frame_offset += $frame_bytesvolume;
1244 }
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;
1251 }
1252 $frame_offset += $frame_bytesvolume;
1253 $parsedFrame[
'peakvolume'][
'bass'] =
getid3_lib::BigEndian2Int(substr($parsedFrame[
'data'], $frame_offset, $frame_bytesvolume));
1254 $frame_offset += $frame_bytesvolume;
1255 }
1256 }
1257 unset($parsedFrame['data']);
1258
1259
1260 } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'EQU2')) {
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272 $frame_offset = 0;
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 = '';
1278 }
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);
1285 }
1286 $parsedFrame['interpolationmethod'] = $frame_interpolationmethod;
1287 unset($parsedFrame['data']);
1288
1289
1290 } elseif ((($id3v2_majorversion == 3) && ($parsedFrame['frame_name'] == 'EQUA')) ||
1291 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'EQU'))) {
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302 $frame_offset = 0;
1303 $parsedFrame['adjustmentbits'] = substr($parsedFrame['data'], $frame_offset++, 1);
1304 $frame_adjustmentbytes = ceil($parsedFrame['adjustmentbits'] / 8);
1305
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;
1315 }
1316 $frame_remainingdata = substr($frame_remainingdata, 2 + $frame_adjustmentbytes);
1317 }
1318 unset($parsedFrame['data']);
1319
1320
1321 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'RVRB')) ||
1322 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'REV'))) {
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336 $frame_offset = 0;
1338 $frame_offset += 2;
1340 $frame_offset += 2;
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']);
1350
1351
1352 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'APIC')) ||
1353 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'PIC'))) {
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365 $frame_offset = 0;
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";
1371 }
1372
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') {
1376
1377
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 = '';
1382 }
1383 $frame_imagetype = strtoupper(str_replace('image/', '', strtolower($frame_mimetype)));
1384 if ($frame_imagetype == 'JPEG') {
1385 $frame_imagetype = 'JPG';
1386 }
1387 $frame_offset = $frame_terminatorpos + strlen("\x00");
1388 } else {
1389 $frame_offset += 3;
1390 }
1391 }
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 = '';
1397 }
1398 $frame_offset = $frame_terminatorpos + strlen("\x00");
1399 }
1400
1401 $frame_picturetype = ord(substr($parsedFrame['data'], $frame_offset++, 1));
1402
1403 if ($frame_offset >= $parsedFrame['datalength']) {
1404 $this->
warning(
'data portion of APIC frame is missing at offset '.($parsedFrame[
'dataoffset'] + 8 + $frame_offset));
1405 } else {
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++;
1409 }
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"))) {
1412
1413 $frame_description = '';
1414 }
1415 $parsedFrame['encodingid'] = $frame_textencoding;
1417
1418 if ($id3v2_majorversion == 2) {
1419 $parsedFrame['imagetype'] = $frame_imagetype;
1420 } else {
1421 $parsedFrame['mime'] = $frame_mimetype;
1422 }
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']);
1428
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];
1436 }
1437 if ($imagechunkcheck[1]) {
1438 $parsedFrame['image_height'] = $imagechunkcheck[1];
1439 }
1440 }
1441 }
1442
1443 do {
1444 if ($this->getid3->option_save_attachments === false) {
1445
1446 unset($parsedFrame['data']);
1447 break;
1448 }
1449 if ($this->getid3->option_save_attachments === true) {
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
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)) {
1463
1464 $this->
warning(
'attachment at '.$frame_offset.
' cannot be saved to "'.$dir.
'" (not writable)');
1465 unset($parsedFrame['data']);
1466 break;
1467 }
1468 }
1469
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']);
1474 } else {
1475 $this->
warning(
'attachment at '.$frame_offset.
' cannot be saved to "'.$destination_filename.
'" (not writable)');
1476 }
1477 $parsedFrame['data_filename'] = $destination_filename;
1478 unset($parsedFrame['data']);
1479 } else {
1480 if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
1481 if (!isset(
$info[
'id3v2'][
'comments'][
'picture'])) {
1482 $info[
'id3v2'][
'comments'][
'picture'] = array();
1483 }
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];
1488 }
1489 }
1490 $info[
'id3v2'][
'comments'][
'picture'][] = $comments_picture_data;
1491 unset($comments_picture_data);
1492 }
1493 }
1494 } while (false);
1495 }
1496
1497 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'GEOB')) ||
1498 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'GEO'))) {
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508 $frame_offset = 0;
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";
1514 }
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 = '';
1519 }
1520 $frame_offset = $frame_terminatorpos + strlen("\x00");
1521
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++;
1525 }
1526 $frame_filename = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1527 if (ord($frame_filename) === 0) {
1528 $frame_filename = '';
1529 }
1530 $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
1531
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++;
1535 }
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"))) {
1538
1539 $frame_description = '';
1540 }
1541 $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
1542
1543 $parsedFrame['objectdata'] = (string) substr($parsedFrame['data'], $frame_offset);
1544 $parsedFrame['encodingid'] = $frame_textencoding;
1546
1547 $parsedFrame['mime'] = $frame_mimetype;
1548 $parsedFrame['filename'] = $frame_filename;
1549 $parsedFrame['description'] = $frame_description;
1550 unset($parsedFrame['data']);
1551
1552
1553 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'PCNT')) ||
1554 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'CNT'))) {
1555
1556
1557
1558
1559
1560
1562
1563
1564 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'POPM')) ||
1565 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'POP'))) {
1566
1567
1568
1569
1570
1571
1572
1573 $frame_offset = 0;
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 = '';
1578 }
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']);
1585
1586
1587 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'RBUF')) ||
1588 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'BUF'))) {
1589
1590
1591
1592
1593
1594
1595 $frame_offset = 0;
1597 $frame_offset += 3;
1598
1600 $parsedFrame['flags']['embededinfo'] = (bool) substr($frame_embeddedinfoflags, 7, 1);
1602 unset($parsedFrame['data']);
1603
1604
1605 } elseif (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'CRM')) {
1606
1607
1608
1609
1610
1611
1612
1613 $frame_offset = 0;
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");
1617
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"))) {
1621
1622 $frame_description = '';
1623 }
1624 $frame_offset = $frame_terminatorpos + strlen("\x00");
1625
1626 $parsedFrame['ownerid'] = $frame_ownerid;
1627 $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
1628 $parsedFrame['description'] = $frame_description;
1629 unset($parsedFrame['data']);
1630
1631
1632 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'AENC')) ||
1633 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'CRA'))) {
1634
1635
1636
1637
1638
1639
1640
1641
1642 $frame_offset = 0;
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 = '';
1647 }
1648 $frame_offset = $frame_terminatorpos + strlen("\x00");
1649 $parsedFrame['ownerid'] = $frame_ownerid;
1651 $frame_offset += 2;
1653 $frame_offset += 2;
1654 $parsedFrame['encryptioninfo'] = (string) substr($parsedFrame['data'], $frame_offset);
1655 unset($parsedFrame['data']);
1656
1657
1658 } elseif ((($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'LINK')) ||
1659 (($id3v2_majorversion == 2) && ($parsedFrame['frame_name'] == 'LNK'))) {
1660
1661
1662
1663
1664
1665
1666
1667
1668 $frame_offset = 0;
1669 if ($id3v2_majorversion == 2) {
1670 $parsedFrame['frameid'] = substr($parsedFrame['data'], $frame_offset, 3);
1671 $frame_offset += 3;
1672 } else {
1673 $parsedFrame['frameid'] = substr($parsedFrame['data'], $frame_offset, 4);
1674 $frame_offset += 4;
1675 }
1676
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) {
1680 $frame_url = '';
1681 }
1682 $frame_offset = $frame_terminatorpos + strlen("\x00");
1683 $parsedFrame['url'] = $frame_url;
1684
1685 $parsedFrame['additionaldata'] = (string) substr($parsedFrame['data'], $frame_offset);
1686 if (!empty($parsedFrame['framenameshort']) && $parsedFrame['url']) {
1688 }
1689 unset($parsedFrame['data']);
1690
1691
1692 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'POSS')) {
1693
1694
1695
1696
1697
1698 $frame_offset = 0;
1699 $parsedFrame['timestampformat'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
1701 unset($parsedFrame['data']);
1702
1703
1704 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'USER')) {
1705
1706
1707
1708
1709
1710
1711
1712 $frame_offset = 0;
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');
1716 }
1717 $frame_language = substr($parsedFrame['data'], $frame_offset, 3);
1718 $frame_offset += 3;
1719 $parsedFrame['language'] = $frame_language;
1720 $parsedFrame[
'languagename'] = $this->
LanguageLookup($frame_language,
false);
1721 $parsedFrame['encodingid'] = $frame_textencoding;
1723
1724 $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
1725 if (!empty($parsedFrame['framenameshort']) && !empty($parsedFrame['data'])) {
1727 }
1728 unset($parsedFrame['data']);
1729
1730
1731 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'OWNE')) {
1732
1733
1734
1735
1736
1737
1738
1739 $frame_offset = 0;
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');
1743 }
1744 $parsedFrame['encodingid'] = $frame_textencoding;
1746
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");
1750
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);
1754
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));
1758 }
1759 $frame_offset += 8;
1760
1761 $parsedFrame['seller'] = (string) substr($parsedFrame['data'], $frame_offset);
1762 unset($parsedFrame['data']);
1763
1764
1765 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'COMR')) {
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779 $frame_offset = 0;
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";
1785 }
1786
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);
1795 }
1796
1797 $frame_datestring = substr($parsedFrame['data'], $frame_offset, 8);
1798 $frame_offset += 8;
1799
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");
1803
1804 $frame_receivedasid = ord(substr($parsedFrame['data'], $frame_offset++, 1));
1805
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++;
1809 }
1810 $frame_sellername = substr($parsedFrame['data'], $frame_offset, $frame_terminatorpos - $frame_offset);
1811 if (ord($frame_sellername) === 0) {
1812 $frame_sellername = '';
1813 }
1814 $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
1815
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++;
1819 }
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"))) {
1822
1823 $frame_description = '';
1824 }
1825 $frame_offset = $frame_terminatorpos + strlen($frame_textencoding_terminator);
1826
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");
1830
1831 $frame_sellerlogo = substr($parsedFrame['data'], $frame_offset);
1832
1833 $parsedFrame['encodingid'] = $frame_textencoding;
1835
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']);
1845
1846
1847 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'ENCR')) {
1848
1849
1850
1851
1852
1853
1854
1855
1856 $frame_offset = 0;
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 = '';
1861 }
1862 $frame_offset = $frame_terminatorpos + strlen("\x00");
1863
1864 $parsedFrame['ownerid'] = $frame_ownerid;
1865 $parsedFrame['methodsymbol'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
1866 $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
1867
1868
1869 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'GRID')) {
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879 $frame_offset = 0;
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 = '';
1884 }
1885 $frame_offset = $frame_terminatorpos + strlen("\x00");
1886
1887 $parsedFrame['ownerid'] = $frame_ownerid;
1888 $parsedFrame['groupsymbol'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
1889 $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
1890
1891
1892 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'PRIV')) {
1893
1894
1895
1896
1897
1898
1899 $frame_offset = 0;
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 = '';
1904 }
1905 $frame_offset = $frame_terminatorpos + strlen("\x00");
1906
1907 $parsedFrame['ownerid'] = $frame_ownerid;
1908 $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
1909
1910
1911 } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'SIGN')) {
1912
1913
1914
1915
1916
1917
1918 $frame_offset = 0;
1919 $parsedFrame['groupsymbol'] = ord(substr($parsedFrame['data'], $frame_offset++, 1));
1920 $parsedFrame['data'] = (string) substr($parsedFrame['data'], $frame_offset);
1921
1922
1923 } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'SEEK')) {
1924
1925
1926
1927
1928 $frame_offset = 0;
1930
1931
1932 } elseif (($id3v2_majorversion >= 4) && ($parsedFrame['frame_name'] == 'ASPI')) {
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942 $frame_offset = 0;
1944 $frame_offset += 4;
1946 $frame_offset += 4;
1948 $frame_offset += 2;
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;
1954 }
1955 unset($parsedFrame['data']);
1956
1957 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'RGAD')) {
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969 $frame_offset = 0;
1971 $frame_offset += 4;
1972 $rg_track_adjustment =
getid3_lib::Dec2Bin(substr($parsedFrame[
'data'], $frame_offset, 2));
1973 $frame_offset += 2;
1974 $rg_album_adjustment =
getid3_lib::Dec2Bin(substr($parsedFrame[
'data'], $frame_offset, 2));
1975 $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']);
1990
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'];
1996
1997 unset($parsedFrame['data']);
1998
1999 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'CHAP')) {
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009 $frame_offset = 0;
2010 @list($parsedFrame['element_id']) = explode("\x00", $parsedFrame['data'], 2);
2011 $frame_offset += strlen($parsedFrame['element_id']."\x00");
2013 $frame_offset += 4;
2015 $frame_offset += 4;
2016 if (substr($parsedFrame['data'], $frame_offset, 4) != "\xFF\xFF\xFF\xFF") {
2017
2019 }
2020 $frame_offset += 4;
2021 if (substr($parsedFrame['data'], $frame_offset, 4) != "\xFF\xFF\xFF\xFF") {
2022
2024 }
2025 $frame_offset += 4;
2026
2027 if ($frame_offset < strlen($parsedFrame['data'])) {
2028 $parsedFrame['subframes'] = array();
2029 while ($frame_offset < strlen($parsedFrame['data'])) {
2030
2031 $subframe = array();
2032 $subframe['name'] = substr($parsedFrame['data'], $frame_offset, 4);
2033 $frame_offset += 4;
2035 $frame_offset += 4;
2037 $frame_offset += 2;
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)');
2040 break;
2041 }
2042 $subframe_rawdata = substr($parsedFrame['data'], $frame_offset, $subframe['size']);
2043 $frame_offset += $subframe['size'];
2044
2045 $subframe['encodingid'] = ord(substr($subframe_rawdata, 0, 1));
2046 $subframe['text'] = substr($subframe_rawdata, 1);
2049 switch (substr($encoding_converted_text, 0, 2)) {
2050 case "\xFF\xFE":
2051 case "\xFE\xFF":
2052 switch (strtoupper(
$info[
'id3v2'][
'encoding'])) {
2053 case 'ISO-8859-1':
2054 case 'UTF-8':
2055 $encoding_converted_text = substr($encoding_converted_text, 2);
2056
2057 break;
2058 default:
2059
2060 break;
2061 }
2062 break;
2063 default:
2064
2065 break;
2066 }
2067
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;
2073 }
2074 $parsedFrame['subframes'][] = $subframe;
2075 } else {
2076 $this->
warning(
'ID3v2.CHAP subframe "'.$subframe[
'name'].
'" not handled (only TIT2 and TIT3)');
2077 }
2078 }
2079 unset($subframe_rawdata, $subframe, $encoding_converted_text);
2080 }
2081
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];
2086 }
2087 }
2088 if (!isset(
$info[
'id3v2'][
'chapters'])) {
2089 $info[
'id3v2'][
'chapters'] = array();
2090 }
2091 $info[
'id3v2'][
'chapters'][] = $id3v2_chapter_entry;
2092 unset($id3v2_chapter_entry, $id3v2_chapter_key);
2093
2094
2095 } elseif (($id3v2_majorversion >= 3) && ($parsedFrame['frame_name'] == 'CTOC')) {
2096
2097
2098
2099
2100
2101
2102
2103
2104 $frame_offset = 0;
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));
2108 $frame_offset += 1;
2109 $parsedFrame['entry_count'] = ord(substr($parsedFrame['data'], $frame_offset, 1));
2110 $frame_offset += 1;
2111
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;
2117 }
2118
2119 $parsedFrame['ctoc_flags']['ordered'] = (bool) ($ctoc_flags_raw & 0x01);
2120 $parsedFrame['ctoc_flags']['top_level'] = (bool) ($ctoc_flags_raw & 0x03);
2121
2122 unset($ctoc_flags_raw, $terminator_position);
2123
2124 if ($frame_offset < strlen($parsedFrame['data'])) {
2125 $parsedFrame['subframes'] = array();
2126 while ($frame_offset < strlen($parsedFrame['data'])) {
2127
2128 $subframe = array();
2129 $subframe['name'] = substr($parsedFrame['data'], $frame_offset, 4);
2130 $frame_offset += 4;
2132 $frame_offset += 4;
2134 $frame_offset += 2;
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)');
2137 break;
2138 }
2139 $subframe_rawdata = substr($parsedFrame['data'], $frame_offset, $subframe['size']);
2140 $frame_offset += $subframe['size'];
2141
2142 $subframe['encodingid'] = ord(substr($subframe_rawdata, 0, 1));
2143 $subframe['text'] = substr($subframe_rawdata, 1);
2146 switch (substr($encoding_converted_text, 0, 2)) {
2147 case "\xFF\xFE":
2148 case "\xFE\xFF":
2149 switch (strtoupper(
$info[
'id3v2'][
'encoding'])) {
2150 case 'ISO-8859-1':
2151 case 'UTF-8':
2152 $encoding_converted_text = substr($encoding_converted_text, 2);
2153
2154 break;
2155 default:
2156
2157 break;
2158 }
2159 break;
2160 default:
2161
2162 break;
2163 }
2164
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;
2170 }
2171 $parsedFrame['subframes'][] = $subframe;
2172 } else {
2173 $this->
warning(
'ID3v2.CTOC subframe "'.$subframe[
'name'].
'" not handled (only TIT2 and TIT3)');
2174 }
2175 }
2176 unset($subframe_rawdata, $subframe, $encoding_converted_text);
2177 }
2178
2179 }
2180
2181 return true;
2182 }
static COMRReceivedAsLookup($index)
static IsValidDateStampString($datestamp)
static TextEncodingNameLookup($encoding)
static FrameNameShortLookup($framename)
static APICPictureTypeLookup($index, $returnarray=false)
static TextEncodingTerminatorLookup($encoding)
static ETCOEventLookup($index)
static LanguageLookup($languagecode, $casesensitive=false)
LookupCurrencyUnits($currencyid)
static RVA2ChannelTypeLookup($index)
static FrameNameLongLookup($framename)
static SYTLContentTypeLookup($index)
static RGADadjustmentLookup($rawadjustment, $signbit)
static iconv_fallback($in_charset, $out_charset, $string)
static BigEndian2Bin($byteword)
static GetDataImageSize($imgData, &$imageinfo=array())
static iconv_fallback_iso88591_utf8($string, $bom=false)
static RGADoriginatorLookup($originatorcode)
static Bin2Dec($binstring, $signed=false)
static RGADnameLookup($namecode)
static BigEndian2Float($byteword)