402 if (($this->majorversion < 3) || ($this->majorversion > 4)) {
404 $this->errors[] =
'Only ID3v2.3 and ID3v2.4 are supported in GenerateID3v2FrameData()';
408 switch ($frame_name) {
413 if (strlen($source_data_array[
'data']) > 64) {
414 $this->errors[] =
'Identifier not allowed to be longer than 64 bytes in '.$frame_name.
' (supplied data was '.strlen($source_data_array[
'data']).
' bytes long)';
416 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'ownerid']).
"\x00";
417 $framedata .= substr($source_data_array[
'data'], 0, 64);
426 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
428 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.$this->majorversion;
430 $framedata .= chr($source_data_array[
'encodingid']);
431 $framedata .= $source_data_array[
'description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
432 $framedata .= $source_data_array[
'data'];
441 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
443 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.$this->majorversion;
444 } elseif (!isset($source_data_array[
'data']) || !$this->
IsValidURL($source_data_array[
'data'],
false,
false)) {
447 $this->warnings[] =
'Invalid URL in '.$frame_name.
' ('.$source_data_array[
'data'].
')';
449 $framedata .= chr($source_data_array[
'encodingid']);
450 $framedata .= $source_data_array[
'description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
451 $framedata .= $source_data_array[
'data'];
459 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
461 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.$this->majorversion;
463 $framedata .= chr($source_data_array[
'encodingid']);
464 $framedata .= $source_data_array[
'data'];
471 $framedata .= $source_data_array[
'data'];
485 if (($source_data_array[
'timestampformat'] > 2) || ($source_data_array[
'timestampformat'] < 1)) {
486 $this->errors[] =
'Invalid Time Stamp Format byte in '.$frame_name.
' ('.$source_data_array[
'timestampformat'].
')';
488 $framedata .= chr($source_data_array[
'timestampformat']);
489 foreach ($source_data_array as $key => $val) {
491 $this->errors[] =
'Invalid Event Type byte in '.$frame_name.
' ('.$val[
'typeid'].
')';
492 } elseif (($key !=
'timestampformat') && ($key !=
'flags')) {
493 if (($val[
'timestamp'] > 0) && ($previousETCOtimestamp >= $val[
'timestamp'])) {
496 $this->errors[] =
'Out-of-order timestamp in '.$frame_name.
' ('.$val[
'timestamp'].
') for Event Type ('.$val[
'typeid'].
')';
498 $framedata .= chr($val[
'typeid']);
516 if (($source_data_array[
'framesbetweenreferences'] > 0) && ($source_data_array[
'framesbetweenreferences'] <= 65535)) {
519 $this->errors[] =
'Invalid MPEG Frames Between References in '.$frame_name.
' ('.$source_data_array[
'framesbetweenreferences'].
')';
521 if (($source_data_array[
'bytesbetweenreferences'] > 0) && ($source_data_array[
'bytesbetweenreferences'] <= 16777215)) {
524 $this->errors[] =
'Invalid bytes Between References in '.$frame_name.
' ('.$source_data_array[
'bytesbetweenreferences'].
')';
526 if (($source_data_array[
'msbetweenreferences'] > 0) && ($source_data_array[
'msbetweenreferences'] <= 16777215)) {
529 $this->errors[] =
'Invalid Milliseconds Between References in '.$frame_name.
' ('.$source_data_array[
'msbetweenreferences'].
')';
531 if (!$this->
IsWithinBitRange($source_data_array[
'bitsforbytesdeviation'], 8,
false)) {
532 if (($source_data_array[
'bitsforbytesdeviation'] % 4) == 0) {
533 $framedata .= chr($source_data_array[
'bitsforbytesdeviation']);
535 $this->errors[] =
'Bits For Bytes Deviation in '.$frame_name.
' ('.$source_data_array[
'bitsforbytesdeviation'].
') must be a multiple of 4.';
538 $this->errors[] =
'Invalid Bits For Bytes Deviation in '.$frame_name.
' ('.$source_data_array[
'bitsforbytesdeviation'].
')';
540 if (!$this->
IsWithinBitRange($source_data_array[
'bitsformsdeviation'], 8,
false)) {
541 if (($source_data_array[
'bitsformsdeviation'] % 4) == 0) {
542 $framedata .= chr($source_data_array[
'bitsformsdeviation']);
544 $this->errors[] =
'Bits For Milliseconds Deviation in '.$frame_name.
' ('.$source_data_array[
'bitsforbytesdeviation'].
') must be a multiple of 4.';
547 $this->errors[] =
'Invalid Bits For Milliseconds Deviation in '.$frame_name.
' ('.$source_data_array[
'bitsformsdeviation'].
')';
549 foreach ($source_data_array as $key => $val) {
550 if (($key !=
'framesbetweenreferences') && ($key !=
'bytesbetweenreferences') && ($key !=
'msbetweenreferences') && ($key !=
'bitsforbytesdeviation') && ($key !=
'bitsformsdeviation') && ($key !=
'flags')) {
551 $unwrittenbitstream .= str_pad(
Helper::Dec2Bin($val[
'bytedeviation']), $source_data_array[
'bitsforbytesdeviation'],
'0', STR_PAD_LEFT);
552 $unwrittenbitstream .= str_pad(
Helper::Dec2Bin($val[
'msdeviation']), $source_data_array[
'bitsformsdeviation'],
'0', STR_PAD_LEFT);
555 for ($i = 0; $i < strlen($unwrittenbitstream); $i += 8) {
556 $highnibble = bindec(substr($unwrittenbitstream, $i, 4)) << 4;
557 $lownibble = bindec(substr($unwrittenbitstream, $i + 4, 4));
558 $framedata .= chr($highnibble & $lownibble);
569 if (($source_data_array[
'timestampformat'] > 2) || ($source_data_array[
'timestampformat'] < 1)) {
570 $this->errors[] =
'Invalid Time Stamp Format byte in '.$frame_name.
' ('.$source_data_array[
'timestampformat'].
')';
572 $framedata .= chr($source_data_array[
'timestampformat']);
573 foreach ($source_data_array as $key => $val) {
575 $this->errors[] =
'Invalid Event Type byte in '.$frame_name.
' ('.$val[
'typeid'].
')';
576 } elseif (($key !=
'timestampformat') && ($key !=
'flags')) {
577 if (($val[
'tempo'] < 0) || ($val[
'tempo'] > 510)) {
578 $this->errors[] =
'Invalid Tempo (max = 510) in '.$frame_name.
' ('.$val[
'tempo'].
') at timestamp ('.$val[
'timestamp'].
')';
580 if ($val[
'tempo'] > 255) {
581 $framedata .= chr(255);
582 $val[
'tempo'] -= 255;
584 $framedata .= chr($val[
'tempo']);
598 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
600 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.$this->majorversion;
602 $this->errors[] =
'Invalid Language in '.$frame_name.
' ('.$source_data_array[
'language'].
')';
604 $framedata .= chr($source_data_array[
'encodingid']);
605 $framedata .= strtolower($source_data_array[
'language']);
606 $framedata .= $source_data_array[
'description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
607 $framedata .= $source_data_array[
'data'];
623 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
625 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.$this->majorversion;
627 $this->errors[] =
'Invalid Language in '.$frame_name.
' ('.$source_data_array[
'language'].
')';
628 } elseif (($source_data_array[
'timestampformat'] > 2) || ($source_data_array[
'timestampformat'] < 1)) {
629 $this->errors[] =
'Invalid Time Stamp Format byte in '.$frame_name.
' ('.$source_data_array[
'timestampformat'].
')';
631 $this->errors[] =
'Invalid Content Type byte in '.$frame_name.
' ('.$source_data_array[
'contenttypeid'].
')';
632 } elseif (!is_array($source_data_array[
'data'])) {
633 $this->errors[] =
'Invalid Lyric/Timestamp data in '.$frame_name.
' (must be an array)';
635 $framedata .= chr($source_data_array[
'encodingid']);
636 $framedata .= strtolower($source_data_array[
'language']);
637 $framedata .= chr($source_data_array[
'timestampformat']);
638 $framedata .= chr($source_data_array[
'contenttypeid']);
639 $framedata .= $source_data_array[
'description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
640 ksort($source_data_array[
'data']);
641 foreach ($source_data_array[
'data'] as $key => $val) {
642 $framedata .= $val[
'data'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
654 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
656 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.$this->majorversion;
658 $this->errors[] =
'Invalid Language in '.$frame_name.
' ('.$source_data_array[
'language'].
')';
660 $framedata .= chr($source_data_array[
'encodingid']);
661 $framedata .= strtolower($source_data_array[
'language']);
662 $framedata .= $source_data_array[
'description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
663 $framedata .= $source_data_array[
'data'];
677 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'description']).
"\x00";
678 foreach ($source_data_array as $key => $val) {
679 if ($key !=
'description') {
680 $framedata .= chr($val[
'channeltypeid']);
682 if (!$this->
IsWithinBitRange($source_data_array[
'bitspeakvolume'], 8,
false)) {
683 $framedata .= chr($val[
'bitspeakvolume']);
684 if ($val[
'bitspeakvolume'] > 0) {
688 $this->errors[] =
'Invalid Bits Representing Peak Volume in '.$frame_name.
' ('.$val[
'bitspeakvolume'].
') (range = 0 to 255)';
711 $this->errors[] =
'Invalid Bits For Volume Description byte in '.$frame_name.
' ('.$source_data_array[
'bitsvolume'].
') (range = 1 to 255)';
714 $incdecflag .= $source_data_array[
'incdec'][
'right'] ?
'1' :
'0';
715 $incdecflag .= $source_data_array[
'incdec'][
'left'] ?
'1' :
'0';
716 $incdecflag .= $source_data_array[
'incdec'][
'rightrear'] ?
'1' :
'0';
717 $incdecflag .= $source_data_array[
'incdec'][
'leftrear'] ?
'1' :
'0';
718 $incdecflag .= $source_data_array[
'incdec'][
'center'] ?
'1' :
'0';
719 $incdecflag .= $source_data_array[
'incdec'][
'bass'] ?
'1' :
'0';
720 $framedata .= chr(bindec($incdecflag));
721 $framedata .= chr($source_data_array[
'bitsvolume']);
722 $framedata .=
Helper::BigEndian2String($source_data_array[
'volumechange'][
'right'], ceil($source_data_array[
'bitsvolume'] / 8),
false);
723 $framedata .=
Helper::BigEndian2String($source_data_array[
'volumechange'][
'left'], ceil($source_data_array[
'bitsvolume'] / 8),
false);
724 $framedata .=
Helper::BigEndian2String($source_data_array[
'peakvolume'][
'right'], ceil($source_data_array[
'bitsvolume'] / 8),
false);
725 $framedata .=
Helper::BigEndian2String($source_data_array[
'peakvolume'][
'left'], ceil($source_data_array[
'bitsvolume'] / 8),
false);
726 if ($source_data_array[
'volumechange'][
'rightrear'] || $source_data_array[
'volumechange'][
'leftrear'] ||
727 $source_data_array[
'peakvolume'][
'rightrear'] || $source_data_array[
'peakvolume'][
'leftrear'] ||
728 $source_data_array[
'volumechange'][
'center'] || $source_data_array[
'peakvolume'][
'center'] ||
729 $source_data_array[
'volumechange'][
'bass'] || $source_data_array[
'peakvolume'][
'bass']) {
730 $framedata .=
Helper::BigEndian2String($source_data_array[
'volumechange'][
'rightrear'], ceil($source_data_array[
'bitsvolume']/8),
false);
731 $framedata .=
Helper::BigEndian2String($source_data_array[
'volumechange'][
'leftrear'], ceil($source_data_array[
'bitsvolume']/8),
false);
732 $framedata .=
Helper::BigEndian2String($source_data_array[
'peakvolume'][
'rightrear'], ceil($source_data_array[
'bitsvolume']/8),
false);
733 $framedata .=
Helper::BigEndian2String($source_data_array[
'peakvolume'][
'leftrear'], ceil($source_data_array[
'bitsvolume']/8),
false);
735 if ($source_data_array[
'volumechange'][
'center'] || $source_data_array[
'peakvolume'][
'center'] ||
736 $source_data_array[
'volumechange'][
'bass'] || $source_data_array[
'peakvolume'][
'bass']) {
737 $framedata .=
Helper::BigEndian2String($source_data_array[
'volumechange'][
'center'], ceil($source_data_array[
'bitsvolume']/8),
false);
738 $framedata .=
Helper::BigEndian2String($source_data_array[
'peakvolume'][
'center'], ceil($source_data_array[
'bitsvolume']/8),
false);
740 if ($source_data_array[
'volumechange'][
'bass'] || $source_data_array[
'peakvolume'][
'bass']) {
741 $framedata .=
Helper::BigEndian2String($source_data_array[
'volumechange'][
'bass'], ceil($source_data_array[
'bitsvolume']/8),
false);
742 $framedata .=
Helper::BigEndian2String($source_data_array[
'peakvolume'][
'bass'], ceil($source_data_array[
'bitsvolume']/8),
false);
756 if (($source_data_array[
'interpolationmethod'] < 0) || ($source_data_array[
'interpolationmethod'] > 1)) {
757 $this->errors[] =
'Invalid Interpolation Method byte in '.$frame_name.
' ('.$source_data_array[
'interpolationmethod'].
') (valid = 0 or 1)';
759 $framedata .= chr($source_data_array[
'interpolationmethod']);
760 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'description']).
"\x00";
761 foreach ($source_data_array[
'data'] as $key => $val) {
778 $this->errors[] =
'Invalid Adjustment Bits byte in '.$frame_name.
' ('.$source_data_array[
'bitsvolume'].
') (range = 1 to 255)';
780 $framedata .= chr($source_data_array[
'adjustmentbits']);
781 foreach ($source_data_array as $key => $val) {
782 if ($key !=
'bitsvolume') {
783 if (($key > 32767) || ($key < 0)) {
784 $this->errors[] =
'Invalid Frequency in '.$frame_name.
' ('.$key.
') (range = 0 to 32767)';
811 $this->errors[] =
'Invalid Reverb Left in '.$frame_name.
' ('.$source_data_array[
'left'].
') (range = 0 to 65535)';
812 } elseif (!$this->
IsWithinBitRange($source_data_array[
'right'], 16,
false)) {
813 $this->errors[] =
'Invalid Reverb Left in '.$frame_name.
' ('.$source_data_array[
'right'].
') (range = 0 to 65535)';
814 } elseif (!$this->
IsWithinBitRange($source_data_array[
'bouncesL'], 8,
false)) {
815 $this->errors[] =
'Invalid Reverb Bounces, Left in '.$frame_name.
' ('.$source_data_array[
'bouncesL'].
') (range = 0 to 255)';
816 } elseif (!$this->
IsWithinBitRange($source_data_array[
'bouncesR'], 8,
false)) {
817 $this->errors[] =
'Invalid Reverb Bounces, Right in '.$frame_name.
' ('.$source_data_array[
'bouncesR'].
') (range = 0 to 255)';
818 } elseif (!$this->
IsWithinBitRange($source_data_array[
'feedbackLL'], 8,
false)) {
819 $this->errors[] =
'Invalid Reverb Feedback, Left-To-Left in '.$frame_name.
' ('.$source_data_array[
'feedbackLL'].
') (range = 0 to 255)';
820 } elseif (!$this->
IsWithinBitRange($source_data_array[
'feedbackLR'], 8,
false)) {
821 $this->errors[] =
'Invalid Reverb Feedback, Left-To-Right in '.$frame_name.
' ('.$source_data_array[
'feedbackLR'].
') (range = 0 to 255)';
822 } elseif (!$this->
IsWithinBitRange($source_data_array[
'feedbackRR'], 8,
false)) {
823 $this->errors[] =
'Invalid Reverb Feedback, Right-To-Right in '.$frame_name.
' ('.$source_data_array[
'feedbackRR'].
') (range = 0 to 255)';
824 } elseif (!$this->
IsWithinBitRange($source_data_array[
'feedbackRL'], 8,
false)) {
825 $this->errors[] =
'Invalid Reverb Feedback, Right-To-Left in '.$frame_name.
' ('.$source_data_array[
'feedbackRL'].
') (range = 0 to 255)';
826 } elseif (!$this->
IsWithinBitRange($source_data_array[
'premixLR'], 8,
false)) {
827 $this->errors[] =
'Invalid Premix, Left-To-Right in '.$frame_name.
' ('.$source_data_array[
'premixLR'].
') (range = 0 to 255)';
828 } elseif (!$this->
IsWithinBitRange($source_data_array[
'premixRL'], 8,
false)) {
829 $this->errors[] =
'Invalid Premix, Right-To-Left in '.$frame_name.
' ('.$source_data_array[
'premixRL'].
') (range = 0 to 255)';
833 $framedata .= chr($source_data_array[
'bouncesL']);
834 $framedata .= chr($source_data_array[
'bouncesR']);
835 $framedata .= chr($source_data_array[
'feedbackLL']);
836 $framedata .= chr($source_data_array[
'feedbackLR']);
837 $framedata .= chr($source_data_array[
'feedbackRR']);
838 $framedata .= chr($source_data_array[
'feedbackRL']);
839 $framedata .= chr($source_data_array[
'premixLR']);
840 $framedata .= chr($source_data_array[
'premixRL']);
851 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
853 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.$this->majorversion;
855 $this->errors[] =
'Invalid Picture Type byte in '.$frame_name.
' ('.$source_data_array[
'picturetypeid'].
') for ID3v2.'.$this->majorversion;
857 $this->errors[] =
'Invalid MIME Type in '.$frame_name.
' ('.$source_data_array[
'mime'].
') for ID3v2.'.$this->majorversion;
858 } elseif (($source_data_array[
'mime'] ==
'-->') && (!$this->
IsValidURL($source_data_array[
'data'],
false,
false))) {
861 $this->warnings[] =
'Invalid URL in '.$frame_name.
' ('.$source_data_array[
'data'].
')';
863 $framedata .= chr($source_data_array[
'encodingid']);
864 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'mime']).
"\x00";
865 $framedata .= chr($source_data_array[
'picturetypeid']);
866 $framedata .= (!empty($source_data_array[
'description']) ? $source_data_array[
'description'] :
'').Tag\
Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
867 $framedata .= $source_data_array[
'data'];
878 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
880 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.$this->majorversion;
882 $this->errors[] =
'Invalid MIME Type in '.$frame_name.
' ('.$source_data_array[
'mime'].
')';
883 } elseif (!$source_data_array[
'description']) {
884 $this->errors[] =
'Missing Description in '.$frame_name;
886 $framedata .= chr($source_data_array[
'encodingid']);
887 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'mime']).
"\x00";
888 $framedata .= $source_data_array[
'filename'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
889 $framedata .= $source_data_array[
'description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
890 $framedata .= $source_data_array[
'data'];
910 $this->errors[] =
'Invalid Rating byte in '.$frame_name.
' ('.$source_data_array[
'rating'].
') (range = 0 to 255)';
911 } elseif (!IsValidEmail($source_data_array[
'email'])) {
912 $this->errors[] =
'Invalid Email in '.$frame_name.
' ('.$source_data_array[
'email'].
')';
914 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'email']).
"\x00";
915 $framedata .= chr($source_data_array[
'rating']);
925 if (!$this->
IsWithinBitRange($source_data_array[
'buffersize'], 24,
false)) {
926 $this->errors[] =
'Invalid Buffer Size in '.$frame_name;
927 } elseif (!$this->
IsWithinBitRange($source_data_array[
'nexttagoffset'], 32,
false)) {
928 $this->errors[] =
'Invalid Offset To Next Tag in '.$frame_name;
932 $flag .= $source_data_array[
'flags'][
'embededinfo'] ?
'1' :
'0';
933 $framedata .= chr(bindec($flag));
944 if (!$this->
IsWithinBitRange($source_data_array[
'previewstart'], 16,
false)) {
945 $this->errors[] =
'Invalid Preview Start in '.$frame_name.
' ('.$source_data_array[
'previewstart'].
')';
946 } elseif (!$this->
IsWithinBitRange($source_data_array[
'previewlength'], 16,
false)) {
947 $this->errors[] =
'Invalid Preview Length in '.$frame_name.
' ('.$source_data_array[
'previewlength'].
')';
949 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'ownerid']).
"\x00";
952 $framedata .= $source_data_array[
'encryptioninfo'];
962 $this->errors[] =
'Invalid Frame Identifier in '.$frame_name.
' ('.$source_data_array[
'frameid'].
')';
963 } elseif (!$this->
IsValidURL($source_data_array[
'data'],
true,
false)) {
966 $this->warnings[] =
'Invalid URL in '.$frame_name.
' ('.$source_data_array[
'data'].
')';
967 } elseif ((($source_data_array[
'frameid'] ==
'AENC') || ($source_data_array[
'frameid'] ==
'APIC') || ($source_data_array[
'frameid'] ==
'GEOB') || ($source_data_array[
'frameid'] ==
'TXXX')) && ($source_data_array[
'additionaldata'] ==
'')) {
968 $this->errors[] =
'Content Descriptor must be specified as additional data for Frame Identifier of '.$source_data_array[
'frameid'].
' in '.$frame_name;
969 } elseif (($source_data_array[
'frameid'] ==
'USER') && (Tag\
Id3v2::LanguageLookup($source_data_array[
'additionaldata'],
true) ==
'')) {
970 $this->errors[] =
'Language must be specified as additional data for Frame Identifier of '.$source_data_array[
'frameid'].
' in '.$frame_name;
971 } elseif (($source_data_array[
'frameid'] ==
'PRIV') && ($source_data_array[
'additionaldata'] ==
'')) {
972 $this->errors[] =
'Owner Identifier must be specified as additional data for Frame Identifier of '.$source_data_array[
'frameid'].
' in '.$frame_name;
973 } elseif ((($source_data_array[
'frameid'] ==
'COMM') || ($source_data_array[
'frameid'] ==
'SYLT') || ($source_data_array[
'frameid'] ==
'USLT')) && ((Tag\
Id3v2::LanguageLookup(substr($source_data_array[
'additionaldata'], 0, 3),
true) ==
'') || (substr($source_data_array[
'additionaldata'], 3) ==
''))) {
974 $this->errors[] =
'Language followed by Content Descriptor must be specified as additional data for Frame Identifier of '.$source_data_array[
'frameid'].
' in '.$frame_name;
976 $framedata .= $source_data_array[
'frameid'];
977 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'data']).
"\x00";
978 switch ($source_data_array[
'frameid']) {
988 $framedata .= $source_data_array[
'additionaldata'];
1005 if ($this->majorversion == 3) {
1008 $this->errors[] = $source_data_array[
'frameid'].
' is not a valid Frame Identifier in '.$frame_name.
' (in ID3v2.'.$this->majorversion.
')';
1012 if ((substr($source_data_array[
'frameid'], 0, 1) ==
'T') || (substr($source_data_array[
'frameid'], 0, 1) ==
'W')) {
1015 $this->errors[] = $source_data_array[
'frameid'].
' is not a valid Frame Identifier in '.$frame_name.
' (in ID3v2.'.$this->majorversion.
')';
1026 if (($source_data_array[
'timestampformat'] < 1) || ($source_data_array[
'timestampformat'] > 2)) {
1027 $this->errors[] =
'Invalid Time Stamp Format in '.$frame_name.
' ('.$source_data_array[
'timestampformat'].
') (valid = 1 or 2)';
1028 } elseif (!$this->
IsWithinBitRange($source_data_array[
'position'], 32,
false)) {
1029 $this->errors[] =
'Invalid Position in '.$frame_name.
' ('.$source_data_array[
'position'].
') (range = 0 to 4294967295)';
1031 $framedata .= chr($source_data_array[
'timestampformat']);
1041 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
1043 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
')';
1045 $this->errors[] =
'Invalid Language in '.$frame_name.
' ('.$source_data_array[
'language'].
')';
1047 $framedata .= chr($source_data_array[
'encodingid']);
1048 $framedata .= strtolower($source_data_array[
'language']);
1049 $framedata .= $source_data_array[
'data'];
1059 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
1061 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
')';
1062 } elseif (!$this->
IsANumber($source_data_array[
'pricepaid'][
'value'],
false)) {
1063 $this->errors[] =
'Invalid Price Paid in '.$frame_name.
' ('.$source_data_array[
'pricepaid'][
'value'].
')';
1065 $this->errors[] =
'Invalid Date Of Purchase in '.$frame_name.
' ('.$source_data_array[
'purchasedate'].
') (format = YYYYMMDD)';
1067 $framedata .= chr($source_data_array[
'encodingid']);
1068 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'pricepaid'][
'value']).
"\x00";
1069 $framedata .= $source_data_array[
'purchasedate'];
1070 $framedata .= $source_data_array[
'seller'];
1085 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
1087 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
')';
1089 $this->errors[] =
'Invalid Valid Until date in '.$frame_name.
' ('.$source_data_array[
'pricevaliduntil'].
') (format = YYYYMMDD)';
1090 } elseif (!$this->
IsValidURL($source_data_array[
'contacturl'],
false,
true)) {
1091 $this->errors[] =
'Invalid Contact URL in '.$frame_name.
' ('.$source_data_array[
'contacturl'].
') (allowed schemes: http, https, ftp, mailto)';
1093 $this->errors[] =
'Invalid Received As byte in '.$frame_name.
' ('.$source_data_array[
'contacturl'].
') (range = 0 to 8)';
1095 $this->errors[] =
'Invalid MIME Type in '.$frame_name.
' ('.$source_data_array[
'mime'].
')';
1097 $framedata .= chr($source_data_array[
'encodingid']);
1098 unset($pricestring);
1099 foreach ($source_data_array[
'price'] as $key => $val) {
1101 $pricestrings[] = $key.$val[
'value'];
1103 $this->errors[] =
'Invalid Price String in '.$frame_name.
' ('.$key.$val[
'value'].
')';
1106 $framedata .= implode(
'/', $pricestrings);
1107 $framedata .= $source_data_array[
'pricevaliduntil'];
1108 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'contacturl']).
"\x00";
1109 $framedata .= chr($source_data_array[
'receivedasid']);
1110 $framedata .= $source_data_array[
'sellername'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
1111 $framedata .= $source_data_array[
'description'].Tag\Id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
1112 $framedata .= $source_data_array[
'mime'].
"\x00";
1113 $framedata .= $source_data_array[
'logo'];
1122 if (!$this->
IsWithinBitRange($source_data_array[
'methodsymbol'], 8,
false)) {
1123 $this->errors[] =
'Invalid Group Symbol in '.$frame_name.
' ('.$source_data_array[
'methodsymbol'].
') (range = 0 to 255)';
1125 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'ownerid']).
"\x00";
1126 $framedata .= ord($source_data_array[
'methodsymbol']);
1127 $framedata .= $source_data_array[
'data'];
1136 if (!$this->
IsWithinBitRange($source_data_array[
'groupsymbol'], 8,
false)) {
1137 $this->errors[] =
'Invalid Group Symbol in '.$frame_name.
' ('.$source_data_array[
'groupsymbol'].
') (range = 0 to 255)';
1139 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'ownerid']).
"\x00";
1140 $framedata .= ord($source_data_array[
'groupsymbol']);
1141 $framedata .= $source_data_array[
'data'];
1149 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'ownerid']).
"\x00";
1150 $framedata .= $source_data_array[
'data'];
1157 if (!$this->
IsWithinBitRange($source_data_array[
'groupsymbol'], 8,
false)) {
1158 $this->errors[] =
'Invalid Group Symbol in '.$frame_name.
' ('.$source_data_array[
'groupsymbol'].
') (range = 0 to 255)';
1160 $framedata .= ord($source_data_array[
'groupsymbol']);
1161 $framedata .= $source_data_array[
'data'];
1169 $this->errors[] =
'Invalid Minimum Offset in '.$frame_name.
' ('.$source_data_array[
'data'].
') (range = 0 to 4294967295)';
1183 if (!$this->
IsWithinBitRange($source_data_array[
'datastart'], 32,
false)) {
1184 $this->errors[] =
'Invalid Indexed Data Start in '.$frame_name.
' ('.$source_data_array[
'datastart'].
') (range = 0 to 4294967295)';
1185 } elseif (!$this->
IsWithinBitRange($source_data_array[
'datalength'], 32,
false)) {
1186 $this->errors[] =
'Invalid Indexed Data Length in '.$frame_name.
' ('.$source_data_array[
'datalength'].
') (range = 0 to 4294967295)';
1187 } elseif (!$this->
IsWithinBitRange($source_data_array[
'indexpoints'], 16,
false)) {
1188 $this->errors[] =
'Invalid Number Of Index Points in '.$frame_name.
' ('.$source_data_array[
'indexpoints'].
') (range = 0 to 65535)';
1189 } elseif (!$this->
IsWithinBitRange($source_data_array[
'bitsperpoint'], 8,
false)) {
1190 $this->errors[] =
'Invalid Bits Per Index Point in '.$frame_name.
' ('.$source_data_array[
'bitsperpoint'].
') (range = 0 to 255)';
1191 } elseif ($source_data_array[
'indexpoints'] != count($source_data_array[
'indexes'])) {
1192 $this->errors[] =
'Number Of Index Points does not match actual supplied data in '.$frame_name;
1198 foreach ($source_data_array[
'indexes'] as $key => $val) {
1215 if (($source_data_array[
'track_adjustment'] > 51) || ($source_data_array[
'track_adjustment'] < -51)) {
1216 $this->errors[] =
'Invalid Track Adjustment in '.$frame_name.
' ('.$source_data_array[
'track_adjustment'].
') (range = -51.0 to +51.0)';
1217 } elseif (($source_data_array[
'album_adjustment'] > 51) || ($source_data_array[
'album_adjustment'] < -51)) {
1218 $this->errors[] =
'Invalid Album Adjustment in '.$frame_name.
' ('.$source_data_array[
'album_adjustment'].
') (range = -51.0 to +51.0)';
1220 $this->errors[] =
'Invalid Track Name Code in '.$frame_name.
' ('.$source_data_array[
'raw'][
'track_name'].
') (range = 0 to 2)';
1222 $this->errors[] =
'Invalid Album Name Code in '.$frame_name.
' ('.$source_data_array[
'raw'][
'album_name'].
') (range = 0 to 2)';
1224 $this->errors[] =
'Invalid Track Originator Code in '.$frame_name.
' ('.$source_data_array[
'raw'][
'track_originator'].
') (range = 0 to 3)';
1226 $this->errors[] =
'Invalid Album Originator Code in '.$frame_name.
' ('.$source_data_array[
'raw'][
'album_originator'].
') (range = 0 to 3)';
1229 $framedata .=
Helper::RGADgainString($source_data_array[
'raw'][
'track_name'], $source_data_array[
'raw'][
'track_originator'], $source_data_array[
'track_adjustment']);
1230 $framedata .=
Helper::RGADgainString($source_data_array[
'raw'][
'album_name'], $source_data_array[
'raw'][
'album_originator'], $source_data_array[
'album_adjustment']);
1235 if ((($this->majorversion == 2) && (strlen($frame_name) != 3)) || (($this->majorversion > 2) && (strlen($frame_name) != 4))) {
1236 $this->errors[] =
'Invalid frame name "'.$frame_name.
'" for ID3v2.'.$this->majorversion;
1237 } elseif ($frame_name{0} ==
'T') {
1241 $source_data_array[
'encodingid'] = (isset($source_data_array[
'encodingid']) ? $source_data_array[
'encodingid'] : $this->id3v2_default_encodingid);
1243 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.$this->majorversion;
1245 $framedata .= chr($source_data_array[
'encodingid']);
1246 $framedata .= $source_data_array[
'data'];
1248 } elseif ($frame_name{0} ==
'W') {
1251 if (!$this->
IsValidURL($source_data_array[
'data'],
false,
false)) {
1254 $this->warnings[] =
'Invalid URL in '.$frame_name.
' ('.$source_data_array[
'data'].
')';
1256 $framedata .= $source_data_array[
'data'];
1259 $this->errors[] = $frame_name.
' not yet supported in $this->GenerateID3v2FrameData()';
1264 if (!empty($this->errors)) {
static IsValidID3v2FrameName($framename, $id3v2majorversion)
ID3v2IsValidAPICpicturetype($picturetype)
IsWithinBitRange($number, $maxbits, $signed=false)
static Float2String($floatvalue, $bits)
static BigEndian2String($number, $minbytes=1, $synchsafe=false, $signed=false)
static LanguageLookup($languagecode, $casesensitive=false)
ID3v2IsValidPriceString($pricestring)
ID3v2IsValidCOMRreceivedAs($receivedas)
ID3v2IsValidETCOevent($eventid)
static IsValidDateStampString($datestamp)
ID3v2IsValidTextEncoding($textencodingbyte)
array $ID3v2IsValidTextEncoding_cache
static TextEncodingTerminatorLookup($encoding)
array $TextEncodingTerminatorLookup
ID3v2IsValidRGADname($RGADname)
ID3v2IsValidSYLTtype($contenttype)
static RGADgainString($namecode, $originatorcode, $replaygain)
IsValidURL($url, $allowUserPass=false)
IsValidMIMEstring($mimestring)
ID3v2IsValidAPICimageformat($imageformat)
static IsANumber($numberstring, $allowdecimal=false, $allownegative=false)
ID3v2IsValidRGADoriginator($RGADoriginator)