39 if (is_writeable($this->filename) || (!file_exists($this->filename) && is_writeable(dirname($this->filename)))) {
42 $OldThisFileInfo = $getID3->
analyze($this->filename);
43 if ($this->merge_existing_data) {
45 if (!empty($OldThisFileInfo[
'id3v2'])) {
46 $this->tag_data = $this->
array_join_merge($OldThisFileInfo[
'id3v2'], $this->tag_data);
49 $this->paddedlength = max(@$OldThisFileInfo[
'id3v2'][
'headerlength'], $this->paddedlength);
53 if (file_exists($this->filename) && is_writeable($this->filename) && isset($OldThisFileInfo[
'id3v2'][
'headerlength']) && ($OldThisFileInfo[
'id3v2'][
'headerlength'] == strlen($NewID3v2Tag))) {
56 if (file_exists($this->filename)) {
59 if ($fp = fopen($this->filename,
'r+b')) {
61 fwrite($fp, $NewID3v2Tag, strlen($NewID3v2Tag));
64 $this->errors[] =
'Could not open '.$this->filename.
' mode "r+b" - '.strip_tags(ob_get_contents());
71 if ($fp = fopen($this->filename,
'wb')) {
73 fwrite($fp, $NewID3v2Tag, strlen($NewID3v2Tag));
76 $this->errors[] =
'Could not open '.$this->filename.
' mode "wb" - '.strip_tags(ob_get_contents());
84 if ($tempfilename = tempnam(
'*',
'getID3')) {
86 if ($fp_source = fopen($this->filename,
'rb')) {
87 if ($fp_temp = fopen($tempfilename,
'wb')) {
89 fwrite($fp_temp, $NewID3v2Tag, strlen($NewID3v2Tag));
92 if (!empty($OldThisFileInfo[
'avdataoffset'])) {
93 fseek($fp_source, $OldThisFileInfo[
'avdataoffset'], SEEK_SET);
97 fwrite($fp_temp, $buffer, strlen($buffer));
102 copy($tempfilename, $this->filename);
103 unlink($tempfilename);
109 $this->errors[] =
'Could not open '.$tempfilename.
' mode "wb" - '.strip_tags(ob_get_contents());
116 $this->errors[] =
'Could not open '.$this->filename.
' mode "rb" - '.strip_tags(ob_get_contents());
127 $this->errors[] =
'$this->GenerateID3v2Tag() failed';
131 if (!empty($this->errors)) {
136 $this->errors[] =
'!is_writeable('.$this->filename.
')';
145 if (is_writeable(dirname($this->filename))) {
149 if ($fp_source = @fopen($this->filename,
'rb')) {
152 $OldThisFileInfo = $getID3->
analyze($this->filename);
154 if ($OldThisFileInfo[
'avdataoffset'] !==
false) {
155 fseek($fp_source, $OldThisFileInfo[
'avdataoffset'], SEEK_SET);
157 if ($fp_temp = @fopen($this->filename.
'getid3tmp',
'w+b')) {
159 fwrite($fp_temp, $buffer, strlen($buffer));
163 $this->errors[] =
'Could not open '.$this->filename.
'getid3tmp mode "w+b"';
167 $this->errors[] =
'Could not open '.$this->filename.
' mode "rb"';
169 if (file_exists($this->filename)) {
170 unlink($this->filename);
172 rename($this->filename.
'getid3tmp', $this->filename);
174 } elseif (is_writable($this->filename)) {
178 if ($fp_source = @fopen($this->filename,
'rb')) {
181 $OldThisFileInfo = $getID3->
analyze($this->filename);
183 if ($OldThisFileInfo[
'avdataoffset'] !==
false) {
184 fseek($fp_source, $OldThisFileInfo[
'avdataoffset'], SEEK_SET);
186 if ($fp_temp = tmpfile()) {
188 fwrite($fp_temp, $buffer, strlen($buffer));
191 if ($fp_source = @fopen($this->filename,
'wb')) {
194 fwrite($fp_source, $buffer, strlen($buffer));
196 fseek($fp_temp, -128, SEEK_END);
199 $this->errors[] =
'Could not open '.$this->filename.
' mode "wb"';
203 $this->errors[] =
'Could not create tmpfile()';
206 $this->errors[] =
'Could not open '.$this->filename.
' mode "rb"';
211 $this->errors[] =
'Directory and file both not writeable';
215 if (!empty($this->errors)) {
223 switch ($this->majorversion) {
226 $flag = (@$flags[
'unsynchronisation'] ?
'1' :
'0');
227 $flag .= (@$flags[
'extendedheader'] ?
'1' :
'0');
228 $flag .= (@$flags[
'experimental'] ?
'1' :
'0');
229 $flag .= (@$flags[
'footer'] ?
'1' :
'0');
235 $flag = (@$flags[
'unsynchronisation'] ?
'1' :
'0');
236 $flag .= (@$flags[
'extendedheader'] ?
'1' :
'0');
237 $flag .= (@$flags[
'experimental'] ?
'1' :
'0');
243 $flag = (@$flags[
'unsynchronisation'] ?
'1' :
'0');
244 $flag .= (@$flags[
'compression'] ?
'1' :
'0');
252 return chr(bindec($flag));
256 function GenerateID3v2FrameFlags($TagAlter=
false, $FileAlter=
false, $ReadOnly=
false, $Compression=
false, $Encryption=
false, $GroupingIdentity=
false, $Unsynchronisation=
false, $DataLengthIndicator=
false) {
257 switch ($this->majorversion) {
261 $flag1 .= $TagAlter ?
'1' :
'0';
262 $flag1 .= $FileAlter ?
'1' :
'0';
263 $flag1 .= $ReadOnly ?
'1' :
'0';
267 $flag2 .= $GroupingIdentity ?
'1' :
'0';
269 $flag2 .= $Compression ?
'1' :
'0';
270 $flag2 .= $Encryption ?
'1' :
'0';
271 $flag2 .= $Unsynchronisation ?
'1' :
'0';
272 $flag2 .= $DataLengthIndicator ?
'1' :
'0';
277 $flag1 = $TagAlter ?
'1' :
'0';
278 $flag1 .= $FileAlter ?
'1' :
'0';
279 $flag1 .= $ReadOnly ?
'1' :
'0';
282 $flag2 = $Compression ?
'1' :
'0';
283 $flag2 .= $Encryption ?
'1' :
'0';
284 $flag2 .= $GroupingIdentity ?
'1' :
'0';
293 return chr(bindec($flag1)).chr(bindec($flag2));
302 if (($this->majorversion < 3) || ($this->majorversion > 4)) {
304 $this->errors[] =
'Only ID3v2.3 and ID3v2.4 are supported in GenerateID3v2FrameData()';
308 switch ($frame_name) {
313 if (strlen($source_data_array[
'data']) > 64) {
314 $this->errors[] =
'Identifier not allowed to be longer than 64 bytes in '.$frame_name.
' (supplied data was '.strlen($source_data_array[
'data']).
' bytes long)';
316 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'ownerid']).
"\x00";
317 $framedata .= substr($source_data_array[
'data'], 0, 64);
328 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.
$this->majorversion;
330 $framedata .= chr($source_data_array[
'encodingid']);
331 $framedata .= $source_data_array[
'description'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
332 $framedata .= $source_data_array[
'data'];
343 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.
$this->majorversion;
344 } elseif (!isset($source_data_array[
'data']) || !$this->
IsValidURL($source_data_array[
'data'],
false,
false)) {
347 $this->warnings[] =
'Invalid URL in '.$frame_name.
' ('.$source_data_array[
'data'].
')';
349 $framedata .= chr($source_data_array[
'encodingid']);
350 $framedata .= $source_data_array[
'description'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
351 $framedata .= $source_data_array[
'data'];
361 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.
$this->majorversion;
363 $framedata .= chr($source_data_array[
'encodingid']);
364 $framedata .= $source_data_array[
'data'];
371 $framedata .= $source_data_array[
'data'];
385 if (($source_data_array[
'timestampformat'] > 2) || ($source_data_array[
'timestampformat'] < 1)) {
386 $this->errors[] =
'Invalid Time Stamp Format byte in '.$frame_name.
' ('.$source_data_array[
'timestampformat'].
')';
388 $framedata .= chr($source_data_array[
'timestampformat']);
389 foreach ($source_data_array as $key => $val) {
391 $this->errors[] =
'Invalid Event Type byte in '.$frame_name.
' ('.$val[
'typeid'].
')';
392 } elseif (($key !=
'timestampformat') && ($key !=
'flags')) {
393 if (($val[
'timestamp'] > 0) && ($previousETCOtimestamp >= $val[
'timestamp'])) {
396 $this->errors[] =
'Out-of-order timestamp in '.$frame_name.
' ('.$val[
'timestamp'].
') for Event Type ('.$val[
'typeid'].
')';
398 $framedata .= chr($val[
'typeid']);
416 if (($source_data_array[
'framesbetweenreferences'] > 0) && ($source_data_array[
'framesbetweenreferences'] <= 65535)) {
419 $this->errors[] =
'Invalid MPEG Frames Between References in '.$frame_name.
' ('.$source_data_array[
'framesbetweenreferences'].
')';
421 if (($source_data_array[
'bytesbetweenreferences'] > 0) && ($source_data_array[
'bytesbetweenreferences'] <= 16777215)) {
424 $this->errors[] =
'Invalid bytes Between References in '.$frame_name.
' ('.$source_data_array[
'bytesbetweenreferences'].
')';
426 if (($source_data_array[
'msbetweenreferences'] > 0) && ($source_data_array[
'msbetweenreferences'] <= 16777215)) {
429 $this->errors[] =
'Invalid Milliseconds Between References in '.$frame_name.
' ('.$source_data_array[
'msbetweenreferences'].
')';
431 if (!$this->
IsWithinBitRange($source_data_array[
'bitsforbytesdeviation'], 8,
false)) {
432 if (($source_data_array[
'bitsforbytesdeviation'] % 4) == 0) {
433 $framedata .= chr($source_data_array[
'bitsforbytesdeviation']);
435 $this->errors[] =
'Bits For Bytes Deviation in '.$frame_name.
' ('.$source_data_array[
'bitsforbytesdeviation'].
') must be a multiple of 4.';
438 $this->errors[] =
'Invalid Bits For Bytes Deviation in '.$frame_name.
' ('.$source_data_array[
'bitsforbytesdeviation'].
')';
440 if (!$this->
IsWithinBitRange($source_data_array[
'bitsformsdeviation'], 8,
false)) {
441 if (($source_data_array[
'bitsformsdeviation'] % 4) == 0) {
442 $framedata .= chr($source_data_array[
'bitsformsdeviation']);
444 $this->errors[] =
'Bits For Milliseconds Deviation in '.$frame_name.
' ('.$source_data_array[
'bitsforbytesdeviation'].
') must be a multiple of 4.';
447 $this->errors[] =
'Invalid Bits For Milliseconds Deviation in '.$frame_name.
' ('.$source_data_array[
'bitsformsdeviation'].
')';
449 foreach ($source_data_array as $key => $val) {
450 if (($key !=
'framesbetweenreferences') && ($key !=
'bytesbetweenreferences') && ($key !=
'msbetweenreferences') && ($key !=
'bitsforbytesdeviation') && ($key !=
'bitsformsdeviation') && ($key !=
'flags')) {
451 $unwrittenbitstream .= str_pad(
getid3_lib::Dec2Bin($val[
'bytedeviation']), $source_data_array[
'bitsforbytesdeviation'],
'0', STR_PAD_LEFT);
452 $unwrittenbitstream .= str_pad(
getid3_lib::Dec2Bin($val[
'msdeviation']), $source_data_array[
'bitsformsdeviation'],
'0', STR_PAD_LEFT);
455 for ($i = 0; $i < strlen($unwrittenbitstream); $i += 8) {
456 $highnibble = bindec(substr($unwrittenbitstream, $i, 4)) << 4;
457 $lownibble = bindec(substr($unwrittenbitstream, $i + 4, 4));
458 $framedata .= chr($highnibble & $lownibble);
469 if (($source_data_array[
'timestampformat'] > 2) || ($source_data_array[
'timestampformat'] < 1)) {
470 $this->errors[] =
'Invalid Time Stamp Format byte in '.$frame_name.
' ('.$source_data_array[
'timestampformat'].
')';
472 $framedata .= chr($source_data_array[
'timestampformat']);
473 foreach ($source_data_array as $key => $val) {
475 $this->errors[] =
'Invalid Event Type byte in '.$frame_name.
' ('.$val[
'typeid'].
')';
476 } elseif (($key !=
'timestampformat') && ($key !=
'flags')) {
477 if (($val[
'tempo'] < 0) || ($val[
'tempo'] > 510)) {
478 $this->errors[] =
'Invalid Tempo (max = 510) in '.$frame_name.
' ('.$val[
'tempo'].
') at timestamp ('.$val[
'timestamp'].
')';
480 if ($val[
'tempo'] > 255) {
481 $framedata .= chr(255);
482 $val[
'tempo'] -= 255;
484 $framedata .= chr($val[
'tempo']);
500 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.
$this->majorversion;
502 $this->errors[] =
'Invalid Language in '.$frame_name.
' ('.$source_data_array[
'language'].
')';
504 $framedata .= chr($source_data_array[
'encodingid']);
505 $framedata .= strtolower($source_data_array[
'language']);
506 $framedata .= $source_data_array[
'description'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
507 $framedata .= $source_data_array[
'data'];
525 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.
$this->majorversion;
527 $this->errors[] =
'Invalid Language in '.$frame_name.
' ('.$source_data_array[
'language'].
')';
528 } elseif (($source_data_array[
'timestampformat'] > 2) || ($source_data_array[
'timestampformat'] < 1)) {
529 $this->errors[] =
'Invalid Time Stamp Format byte in '.$frame_name.
' ('.$source_data_array[
'timestampformat'].
')';
531 $this->errors[] =
'Invalid Content Type byte in '.$frame_name.
' ('.$source_data_array[
'contenttypeid'].
')';
532 } elseif (!is_array($source_data_array[
'data'])) {
533 $this->errors[] =
'Invalid Lyric/Timestamp data in '.$frame_name.
' (must be an array)';
535 $framedata .= chr($source_data_array[
'encodingid']);
536 $framedata .= strtolower($source_data_array[
'language']);
537 $framedata .= chr($source_data_array[
'timestampformat']);
538 $framedata .= chr($source_data_array[
'contenttypeid']);
539 $framedata .= $source_data_array[
'description'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
540 ksort($source_data_array[
'data']);
541 foreach ($source_data_array[
'data'] as $key => $val) {
542 $framedata .= $val[
'data'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
556 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.
$this->majorversion;
558 $this->errors[] =
'Invalid Language in '.$frame_name.
' ('.$source_data_array[
'language'].
')';
560 $framedata .= chr($source_data_array[
'encodingid']);
561 $framedata .= strtolower($source_data_array[
'language']);
562 $framedata .= $source_data_array[
'description'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
563 $framedata .= $source_data_array[
'data'];
577 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'description']).
"\x00";
578 foreach ($source_data_array as $key => $val) {
579 if ($key !=
'description') {
580 $framedata .= chr($val[
'channeltypeid']);
582 if (!$this->
IsWithinBitRange($source_data_array[
'bitspeakvolume'], 8,
false)) {
583 $framedata .= chr($val[
'bitspeakvolume']);
584 if ($val[
'bitspeakvolume'] > 0) {
588 $this->errors[] =
'Invalid Bits Representing Peak Volume in '.$frame_name.
' ('.$val[
'bitspeakvolume'].
') (range = 0 to 255)';
611 $this->errors[] =
'Invalid Bits For Volume Description byte in '.$frame_name.
' ('.$source_data_array[
'bitsvolume'].
') (range = 1 to 255)';
614 $incdecflag .= $source_data_array[
'incdec'][
'right'] ?
'1' :
'0';
615 $incdecflag .= $source_data_array[
'incdec'][
'left'] ?
'1' :
'0';
616 $incdecflag .= $source_data_array[
'incdec'][
'rightrear'] ?
'1' :
'0';
617 $incdecflag .= $source_data_array[
'incdec'][
'leftrear'] ?
'1' :
'0';
618 $incdecflag .= $source_data_array[
'incdec'][
'center'] ?
'1' :
'0';
619 $incdecflag .= $source_data_array[
'incdec'][
'bass'] ?
'1' :
'0';
620 $framedata .= chr(bindec($incdecflag));
621 $framedata .= chr($source_data_array[
'bitsvolume']);
622 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'volumechange'][
'right'], ceil($source_data_array[
'bitsvolume'] / 8),
false);
623 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'volumechange'][
'left'], ceil($source_data_array[
'bitsvolume'] / 8),
false);
624 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'peakvolume'][
'right'], ceil($source_data_array[
'bitsvolume'] / 8),
false);
625 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'peakvolume'][
'left'], ceil($source_data_array[
'bitsvolume'] / 8),
false);
626 if ($source_data_array[
'volumechange'][
'rightrear'] || $source_data_array[
'volumechange'][
'leftrear'] ||
627 $source_data_array[
'peakvolume'][
'rightrear'] || $source_data_array[
'peakvolume'][
'leftrear'] ||
628 $source_data_array[
'volumechange'][
'center'] || $source_data_array[
'peakvolume'][
'center'] ||
629 $source_data_array[
'volumechange'][
'bass'] || $source_data_array[
'peakvolume'][
'bass']) {
630 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'volumechange'][
'rightrear'], ceil($source_data_array[
'bitsvolume']/8),
false);
631 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'volumechange'][
'leftrear'], ceil($source_data_array[
'bitsvolume']/8),
false);
632 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'peakvolume'][
'rightrear'], ceil($source_data_array[
'bitsvolume']/8),
false);
633 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'peakvolume'][
'leftrear'], ceil($source_data_array[
'bitsvolume']/8),
false);
635 if ($source_data_array[
'volumechange'][
'center'] || $source_data_array[
'peakvolume'][
'center'] ||
636 $source_data_array[
'volumechange'][
'bass'] || $source_data_array[
'peakvolume'][
'bass']) {
637 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'volumechange'][
'center'], ceil($source_data_array[
'bitsvolume']/8),
false);
638 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'peakvolume'][
'center'], ceil($source_data_array[
'bitsvolume']/8),
false);
640 if ($source_data_array[
'volumechange'][
'bass'] || $source_data_array[
'peakvolume'][
'bass']) {
641 $framedata .=
getid3_lib::BigEndian2String($source_data_array[
'volumechange'][
'bass'], ceil($source_data_array[
'bitsvolume']/8),
false);
656 if (($source_data_array[
'interpolationmethod'] < 0) || ($source_data_array[
'interpolationmethod'] > 1)) {
657 $this->errors[] =
'Invalid Interpolation Method byte in '.$frame_name.
' ('.$source_data_array[
'interpolationmethod'].
') (valid = 0 or 1)';
659 $framedata .= chr($source_data_array[
'interpolationmethod']);
660 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'description']).
"\x00";
661 foreach ($source_data_array[
'data'] as $key => $val) {
678 $this->errors[] =
'Invalid Adjustment Bits byte in '.$frame_name.
' ('.$source_data_array[
'bitsvolume'].
') (range = 1 to 255)';
680 $framedata .= chr($source_data_array[
'adjustmentbits']);
681 foreach ($source_data_array as $key => $val) {
682 if ($key !=
'bitsvolume') {
683 if (($key > 32767) || ($key < 0)) {
684 $this->errors[] =
'Invalid Frequency in '.$frame_name.
' ('.$key.
') (range = 0 to 32767)';
711 $this->errors[] =
'Invalid Reverb Left in '.$frame_name.
' ('.$source_data_array[
'left'].
') (range = 0 to 65535)';
712 } elseif (!$this->
IsWithinBitRange($source_data_array[
'right'], 16,
false)) {
713 $this->errors[] =
'Invalid Reverb Left in '.$frame_name.
' ('.$source_data_array[
'right'].
') (range = 0 to 65535)';
714 } elseif (!$this->
IsWithinBitRange($source_data_array[
'bouncesL'], 8,
false)) {
715 $this->errors[] =
'Invalid Reverb Bounces, Left in '.$frame_name.
' ('.$source_data_array[
'bouncesL'].
') (range = 0 to 255)';
716 } elseif (!$this->
IsWithinBitRange($source_data_array[
'bouncesR'], 8,
false)) {
717 $this->errors[] =
'Invalid Reverb Bounces, Right in '.$frame_name.
' ('.$source_data_array[
'bouncesR'].
') (range = 0 to 255)';
718 } elseif (!$this->
IsWithinBitRange($source_data_array[
'feedbackLL'], 8,
false)) {
719 $this->errors[] =
'Invalid Reverb Feedback, Left-To-Left in '.$frame_name.
' ('.$source_data_array[
'feedbackLL'].
') (range = 0 to 255)';
720 } elseif (!$this->
IsWithinBitRange($source_data_array[
'feedbackLR'], 8,
false)) {
721 $this->errors[] =
'Invalid Reverb Feedback, Left-To-Right in '.$frame_name.
' ('.$source_data_array[
'feedbackLR'].
') (range = 0 to 255)';
722 } elseif (!$this->
IsWithinBitRange($source_data_array[
'feedbackRR'], 8,
false)) {
723 $this->errors[] =
'Invalid Reverb Feedback, Right-To-Right in '.$frame_name.
' ('.$source_data_array[
'feedbackRR'].
') (range = 0 to 255)';
724 } elseif (!$this->
IsWithinBitRange($source_data_array[
'feedbackRL'], 8,
false)) {
725 $this->errors[] =
'Invalid Reverb Feedback, Right-To-Left in '.$frame_name.
' ('.$source_data_array[
'feedbackRL'].
') (range = 0 to 255)';
726 } elseif (!$this->
IsWithinBitRange($source_data_array[
'premixLR'], 8,
false)) {
727 $this->errors[] =
'Invalid Premix, Left-To-Right in '.$frame_name.
' ('.$source_data_array[
'premixLR'].
') (range = 0 to 255)';
728 } elseif (!$this->
IsWithinBitRange($source_data_array[
'premixRL'], 8,
false)) {
729 $this->errors[] =
'Invalid Premix, Right-To-Left in '.$frame_name.
' ('.$source_data_array[
'premixRL'].
') (range = 0 to 255)';
733 $framedata .= chr($source_data_array[
'bouncesL']);
734 $framedata .= chr($source_data_array[
'bouncesR']);
735 $framedata .= chr($source_data_array[
'feedbackLL']);
736 $framedata .= chr($source_data_array[
'feedbackLR']);
737 $framedata .= chr($source_data_array[
'feedbackRR']);
738 $framedata .= chr($source_data_array[
'feedbackRL']);
739 $framedata .= chr($source_data_array[
'premixLR']);
740 $framedata .= chr($source_data_array[
'premixRL']);
753 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.
$this->majorversion;
755 $this->errors[] =
'Invalid Picture Type byte in '.$frame_name.
' ('.$source_data_array[
'picturetypeid'].
') for ID3v2.'.
$this->majorversion;
757 $this->errors[] =
'Invalid MIME Type in '.$frame_name.
' ('.$source_data_array[
'mime'].
') for ID3v2.'.
$this->majorversion;
758 } elseif (($source_data_array[
'mime'] ==
'-->') && (!$this->
IsValidURL($source_data_array[
'data'],
false,
false))) {
761 $this->warnings[] =
'Invalid URL in '.$frame_name.
' ('.$source_data_array[
'data'].
')';
763 $framedata .= chr($source_data_array[
'encodingid']);
764 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'mime']).
"\x00";
765 $framedata .= chr($source_data_array[
'picturetypeid']);
766 $framedata .= @$source_data_array[
'description'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
767 $framedata .= $source_data_array[
'data'];
780 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.
$this->majorversion;
782 $this->errors[] =
'Invalid MIME Type in '.$frame_name.
' ('.$source_data_array[
'mime'].
')';
783 } elseif (!$source_data_array[
'description']) {
784 $this->errors[] =
'Missing Description in '.$frame_name;
786 $framedata .= chr($source_data_array[
'encodingid']);
787 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'mime']).
"\x00";
788 $framedata .= $source_data_array[
'filename'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
789 $framedata .= $source_data_array[
'description'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
790 $framedata .= $source_data_array[
'data'];
810 $this->errors[] =
'Invalid Rating byte in '.$frame_name.
' ('.$source_data_array[
'rating'].
') (range = 0 to 255)';
811 } elseif (!IsValidEmail($source_data_array[
'email'])) {
812 $this->errors[] =
'Invalid Email in '.$frame_name.
' ('.$source_data_array[
'email'].
')';
814 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'email']).
"\x00";
815 $framedata .= chr($source_data_array[
'rating']);
825 if (!$this->
IsWithinBitRange($source_data_array[
'buffersize'], 24,
false)) {
826 $this->errors[] =
'Invalid Buffer Size in '.$frame_name;
827 } elseif (!$this->
IsWithinBitRange($source_data_array[
'nexttagoffset'], 32,
false)) {
828 $this->errors[] =
'Invalid Offset To Next Tag in '.$frame_name;
832 $flag .= $source_data_array[
'flags'][
'embededinfo'] ?
'1' :
'0';
833 $framedata .= chr(bindec($flag));
844 if (!$this->
IsWithinBitRange($source_data_array[
'previewstart'], 16,
false)) {
845 $this->errors[] =
'Invalid Preview Start in '.$frame_name.
' ('.$source_data_array[
'previewstart'].
')';
846 } elseif (!$this->
IsWithinBitRange($source_data_array[
'previewlength'], 16,
false)) {
847 $this->errors[] =
'Invalid Preview Length in '.$frame_name.
' ('.$source_data_array[
'previewlength'].
')';
849 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'ownerid']).
"\x00";
852 $framedata .= $source_data_array[
'encryptioninfo'];
862 $this->errors[] =
'Invalid Frame Identifier in '.$frame_name.
' ('.$source_data_array[
'frameid'].
')';
863 } elseif (!$this->
IsValidURL($source_data_array[
'data'],
true,
false)) {
866 $this->warnings[] =
'Invalid URL in '.$frame_name.
' ('.$source_data_array[
'data'].
')';
867 } 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'] ==
'')) {
868 $this->errors[] =
'Content Descriptor must be specified as additional data for Frame Identifier of '.$source_data_array[
'frameid'].
' in '.$frame_name;
869 } elseif (($source_data_array[
'frameid'] ==
'USER') && (
getid3_id3v2::LanguageLookup($source_data_array[
'additionaldata'],
true) ==
'')) {
870 $this->errors[] =
'Language must be specified as additional data for Frame Identifier of '.$source_data_array[
'frameid'].
' in '.$frame_name;
871 } elseif (($source_data_array[
'frameid'] ==
'PRIV') && ($source_data_array[
'additionaldata'] ==
'')) {
872 $this->errors[] =
'Owner Identifier must be specified as additional data for Frame Identifier of '.$source_data_array[
'frameid'].
' in '.$frame_name;
873 } elseif ((($source_data_array[
'frameid'] ==
'COMM') || ($source_data_array[
'frameid'] ==
'SYLT') || ($source_data_array[
'frameid'] ==
'USLT')) && ((
getid3_id3v2::LanguageLookup(substr($source_data_array[
'additionaldata'], 0, 3),
true) ==
'') || (substr($source_data_array[
'additionaldata'], 3) ==
''))) {
874 $this->errors[] =
'Language followed by Content Descriptor must be specified as additional data for Frame Identifier of '.$source_data_array[
'frameid'].
' in '.$frame_name;
876 $framedata .= $source_data_array[
'frameid'];
877 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'data']).
"\x00";
878 switch ($source_data_array[
'frameid']) {
888 $framedata .= $source_data_array[
'additionaldata'];
905 if ($this->majorversion == 3) {
908 $this->errors[] = $source_data_array[
'frameid'].
' is not a valid Frame Identifier in '.$frame_name.
' (in ID3v2.'.$this->majorversion.
')';
912 if ((substr($source_data_array[
'frameid'], 0, 1) ==
'T') || (substr($source_data_array[
'frameid'], 0, 1) ==
'W')) {
915 $this->errors[] = $source_data_array[
'frameid'].
' is not a valid Frame Identifier in '.$frame_name.
' (in ID3v2.'.$this->majorversion.
')';
926 if (($source_data_array[
'timestampformat'] < 1) || ($source_data_array[
'timestampformat'] > 2)) {
927 $this->errors[] =
'Invalid Time Stamp Format in '.$frame_name.
' ('.$source_data_array[
'timestampformat'].
') (valid = 1 or 2)';
928 } elseif (!$this->
IsWithinBitRange($source_data_array[
'position'], 32,
false)) {
929 $this->errors[] =
'Invalid Position in '.$frame_name.
' ('.$source_data_array[
'position'].
') (range = 0 to 4294967295)';
931 $framedata .= chr($source_data_array[
'timestampformat']);
943 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
')';
945 $this->errors[] =
'Invalid Language in '.$frame_name.
' ('.$source_data_array[
'language'].
')';
947 $framedata .= chr($source_data_array[
'encodingid']);
948 $framedata .= strtolower($source_data_array[
'language']);
949 $framedata .= $source_data_array[
'data'];
961 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
')';
962 } elseif (!$this->IsANumber($source_data_array[
'pricepaid'][
'value'],
false)) {
963 $this->errors[] =
'Invalid Price Paid in '.$frame_name.
' ('.$source_data_array[
'pricepaid'][
'value'].
')';
964 } elseif (!$this->IsValidDateStampString($source_data_array[
'purchasedate'])) {
965 $this->errors[] =
'Invalid Date Of Purchase in '.$frame_name.
' ('.$source_data_array[
'purchasedate'].
') (format = YYYYMMDD)';
967 $framedata .= chr($source_data_array[
'encodingid']);
968 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'pricepaid'][
'value']).
"\x00";
969 $framedata .= $source_data_array[
'purchasedate'];
970 $framedata .= $source_data_array[
'seller'];
987 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
')';
988 } elseif (!$this->IsValidDateStampString($source_data_array[
'pricevaliduntil'])) {
989 $this->errors[] =
'Invalid Valid Until date in '.$frame_name.
' ('.$source_data_array[
'pricevaliduntil'].
') (format = YYYYMMDD)';
990 } elseif (!$this->
IsValidURL($source_data_array[
'contacturl'],
false,
true)) {
991 $this->errors[] =
'Invalid Contact URL in '.$frame_name.
' ('.$source_data_array[
'contacturl'].
') (allowed schemes: http, https, ftp, mailto)';
993 $this->errors[] =
'Invalid Received As byte in '.$frame_name.
' ('.$source_data_array[
'contacturl'].
') (range = 0 to 8)';
995 $this->errors[] =
'Invalid MIME Type in '.$frame_name.
' ('.$source_data_array[
'mime'].
')';
997 $framedata .= chr($source_data_array[
'encodingid']);
999 foreach ($source_data_array[
'price'] as $key => $val) {
1001 $pricestrings[] = $key.$val[
'value'];
1003 $this->errors[] =
'Invalid Price String in '.$frame_name.
' ('.$key.$val[
'value'].
')';
1006 $framedata .= implode(
'/', $pricestrings);
1007 $framedata .= $source_data_array[
'pricevaliduntil'];
1008 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'contacturl']).
"\x00";
1009 $framedata .= chr($source_data_array[
'receivedasid']);
1010 $framedata .= $source_data_array[
'sellername'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
1011 $framedata .= $source_data_array[
'description'].getid3_id3v2::TextEncodingTerminatorLookup($source_data_array[
'encodingid']);
1012 $framedata .= $source_data_array[
'mime'].
"\x00";
1013 $framedata .= $source_data_array[
'logo'];
1022 if (!$this->
IsWithinBitRange($source_data_array[
'methodsymbol'], 8,
false)) {
1023 $this->errors[] =
'Invalid Group Symbol in '.$frame_name.
' ('.$source_data_array[
'methodsymbol'].
') (range = 0 to 255)';
1025 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'ownerid']).
"\x00";
1026 $framedata .= ord($source_data_array[
'methodsymbol']);
1027 $framedata .= $source_data_array[
'data'];
1036 if (!$this->
IsWithinBitRange($source_data_array[
'groupsymbol'], 8,
false)) {
1037 $this->errors[] =
'Invalid Group Symbol in '.$frame_name.
' ('.$source_data_array[
'groupsymbol'].
') (range = 0 to 255)';
1039 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'ownerid']).
"\x00";
1040 $framedata .= ord($source_data_array[
'groupsymbol']);
1041 $framedata .= $source_data_array[
'data'];
1049 $framedata .= str_replace(
"\x00",
'', $source_data_array[
'ownerid']).
"\x00";
1050 $framedata .= $source_data_array[
'data'];
1057 if (!$this->
IsWithinBitRange($source_data_array[
'groupsymbol'], 8,
false)) {
1058 $this->errors[] =
'Invalid Group Symbol in '.$frame_name.
' ('.$source_data_array[
'groupsymbol'].
') (range = 0 to 255)';
1060 $framedata .= ord($source_data_array[
'groupsymbol']);
1061 $framedata .= $source_data_array[
'data'];
1069 $this->errors[] =
'Invalid Minimum Offset in '.$frame_name.
' ('.$source_data_array[
'data'].
') (range = 0 to 4294967295)';
1083 if (!$this->
IsWithinBitRange($source_data_array[
'datastart'], 32,
false)) {
1084 $this->errors[] =
'Invalid Indexed Data Start in '.$frame_name.
' ('.$source_data_array[
'datastart'].
') (range = 0 to 4294967295)';
1085 } elseif (!$this->
IsWithinBitRange($source_data_array[
'datalength'], 32,
false)) {
1086 $this->errors[] =
'Invalid Indexed Data Length in '.$frame_name.
' ('.$source_data_array[
'datalength'].
') (range = 0 to 4294967295)';
1087 } elseif (!$this->
IsWithinBitRange($source_data_array[
'indexpoints'], 16,
false)) {
1088 $this->errors[] =
'Invalid Number Of Index Points in '.$frame_name.
' ('.$source_data_array[
'indexpoints'].
') (range = 0 to 65535)';
1089 } elseif (!$this->
IsWithinBitRange($source_data_array[
'bitsperpoint'], 8,
false)) {
1090 $this->errors[] =
'Invalid Bits Per Index Point in '.$frame_name.
' ('.$source_data_array[
'bitsperpoint'].
') (range = 0 to 255)';
1091 } elseif ($source_data_array[
'indexpoints'] != count($source_data_array[
'indexes'])) {
1092 $this->errors[] =
'Number Of Index Points does not match actual supplied data in '.$frame_name;
1098 foreach ($source_data_array[
'indexes'] as $key => $val) {
1115 if (($source_data_array[
'track_adjustment'] > 51) || ($source_data_array[
'track_adjustment'] < -51)) {
1116 $this->errors[] =
'Invalid Track Adjustment in '.$frame_name.
' ('.$source_data_array[
'track_adjustment'].
') (range = -51.0 to +51.0)';
1117 } elseif (($source_data_array[
'album_adjustment'] > 51) || ($source_data_array[
'album_adjustment'] < -51)) {
1118 $this->errors[] =
'Invalid Album Adjustment in '.$frame_name.
' ('.$source_data_array[
'album_adjustment'].
') (range = -51.0 to +51.0)';
1120 $this->errors[] =
'Invalid Track Name Code in '.$frame_name.
' ('.$source_data_array[
'raw'][
'track_name'].
') (range = 0 to 2)';
1122 $this->errors[] =
'Invalid Album Name Code in '.$frame_name.
' ('.$source_data_array[
'raw'][
'album_name'].
') (range = 0 to 2)';
1124 $this->errors[] =
'Invalid Track Originator Code in '.$frame_name.
' ('.$source_data_array[
'raw'][
'track_originator'].
') (range = 0 to 3)';
1126 $this->errors[] =
'Invalid Album Originator Code in '.$frame_name.
' ('.$source_data_array[
'raw'][
'album_originator'].
') (range = 0 to 3)';
1129 $framedata .=
getid3_lib::RGADgainString($source_data_array[
'raw'][
'track_name'], $source_data_array[
'raw'][
'track_originator'], $source_data_array[
'track_adjustment']);
1130 $framedata .=
getid3_lib::RGADgainString($source_data_array[
'raw'][
'album_name'], $source_data_array[
'raw'][
'album_originator'], $source_data_array[
'album_adjustment']);
1135 if ($frame_name{0} ==
'T') {
1141 $this->errors[] =
'Invalid Text Encoding in '.$frame_name.
' ('.$source_data_array[
'encodingid'].
') for ID3v2.'.
$this->majorversion;
1143 $framedata .= chr($source_data_array[
'encodingid']);
1144 $framedata .= $source_data_array[
'data'];
1146 } elseif ($frame_name{0} ==
'W') {
1149 if (!$this->
IsValidURL($source_data_array[
'data'],
false,
false)) {
1152 $this->warnings[] =
'Invalid URL in '.$frame_name.
' ('.$source_data_array[
'data'].
')';
1154 $framedata .= $source_data_array[
'data'];
1157 $this->errors[] = $frame_name.
' not yet supported in $this->GenerateID3v2FrameData()';
1162 if (!empty($this->errors)) {
1169 static $PreviousFrames = array();
1171 if ($frame_name === null) {
1174 $PreviousFrames = array();
1178 if ($this->majorversion == 4) {
1179 switch ($frame_name) {
1184 if (!isset($source_data_array[
'ownerid'])) {
1185 $this->errors[] =
'[ownerid] not specified for '.$frame_name;
1186 } elseif (in_array($frame_name.$source_data_array[
'ownerid'], $PreviousFrames)) {
1187 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same OwnerID ('.$source_data_array[
'ownerid'].
')';
1189 $PreviousFrames[] = $frame_name.$source_data_array[
'ownerid'];
1199 if (!isset($source_data_array[
'description'])) {
1200 $this->errors[] =
'[description] not specified for '.$frame_name;
1201 } elseif (in_array($frame_name.$source_data_array[
'description'], $PreviousFrames)) {
1202 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Description ('.$source_data_array[
'description'].
')';
1204 $PreviousFrames[] = $frame_name.$source_data_array[
'description'];
1209 if (!isset($source_data_array[
'language'])) {
1210 $this->errors[] =
'[language] not specified for '.$frame_name;
1211 } elseif (in_array($frame_name.$source_data_array[
'language'], $PreviousFrames)) {
1212 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Language ('.$source_data_array[
'language'].
')';
1214 $PreviousFrames[] = $frame_name.$source_data_array[
'language'];
1221 if (!isset($source_data_array[
'language'])) {
1222 $this->errors[] =
'[language] not specified for '.$frame_name;
1223 } elseif (!isset($source_data_array[
'description'])) {
1224 $this->errors[] =
'[description] not specified for '.$frame_name;
1225 } elseif (in_array($frame_name.$source_data_array[
'language'].$source_data_array[
'description'], $PreviousFrames)) {
1226 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Language + Description ('.$source_data_array[
'language'].
' + '.$source_data_array[
'description'].
')';
1228 $PreviousFrames[] = $frame_name.$source_data_array[
'language'].$source_data_array[
'description'];
1233 if (!isset($source_data_array[
'email'])) {
1234 $this->errors[] =
'[email] not specified for '.$frame_name;
1235 } elseif (in_array($frame_name.$source_data_array[
'email'], $PreviousFrames)) {
1236 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Email ('.$source_data_array[
'email'].
')';
1238 $PreviousFrames[] = $frame_name.$source_data_array[
'email'];
1255 if (in_array($frame_name, $PreviousFrames)) {
1256 $this->errors[] =
'Only one '.$frame_name.
' tag allowed';
1258 $PreviousFrames[] = $frame_name;
1265 if (!isset($source_data_array[
'frameid'])) {
1266 $this->errors[] =
'[frameid] not specified for '.$frame_name;
1267 } elseif (in_array($frame_name.$source_data_array[
'frameid'], $PreviousFrames)) {
1268 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same FrameID ('.$source_data_array[
'frameid'].
')';
1269 } elseif (in_array($source_data_array[
'frameid'], $PreviousFrames)) {
1271 $this->errors[] =
'Cannot specify a '.$frame_name.
' tag to a singleton tag that already exists ('.$source_data_array[
'frameid'].
')';
1273 $PreviousFrames[] = $frame_name.$source_data_array[
'frameid'];
1274 $PreviousFrames[] = $source_data_array[
'frameid'];
1285 if (!isset($source_data_array[
'ownerid'])) {
1286 $this->errors[] =
'[ownerid] not specified for '.$frame_name;
1287 } elseif (!isset($source_data_array[
'data'])) {
1288 $this->errors[] =
'[data] not specified for '.$frame_name;
1289 } elseif (in_array($frame_name.$source_data_array[
'ownerid'].$source_data_array[
'data'], $PreviousFrames)) {
1290 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same OwnerID + Data ('.$source_data_array[
'ownerid'].
' + '.$source_data_array[
'data'].
')';
1292 $PreviousFrames[] = $frame_name.$source_data_array[
'ownerid'].$source_data_array[
'data'];
1297 if (($frame_name{0} !=
'T') && ($frame_name{0} !=
'W')) {
1298 $this->errors[] =
'Frame not allowed in ID3v2.'.$this->majorversion.
': '.$frame_name;
1303 } elseif ($this->majorversion == 3) {
1305 switch ($frame_name) {
1310 if (!isset($source_data_array[
'ownerid'])) {
1311 $this->errors[] =
'[ownerid] not specified for '.$frame_name;
1312 } elseif (in_array($frame_name.$source_data_array[
'ownerid'], $PreviousFrames)) {
1313 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same OwnerID ('.$source_data_array[
'ownerid'].
')';
1315 $PreviousFrames[] = $frame_name.$source_data_array[
'ownerid'];
1323 if (!isset($source_data_array[
'description'])) {
1324 $this->errors[] =
'[description] not specified for '.$frame_name;
1325 } elseif (in_array($frame_name.$source_data_array[
'description'], $PreviousFrames)) {
1326 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Description ('.$source_data_array[
'description'].
')';
1328 $PreviousFrames[] = $frame_name.$source_data_array[
'description'];
1333 if (!isset($source_data_array[
'language'])) {
1334 $this->errors[] =
'[language] not specified for '.$frame_name;
1335 } elseif (in_array($frame_name.$source_data_array[
'language'], $PreviousFrames)) {
1336 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Language ('.$source_data_array[
'language'].
')';
1338 $PreviousFrames[] = $frame_name.$source_data_array[
'language'];
1345 if (!isset($source_data_array[
'language'])) {
1346 $this->errors[] =
'[language] not specified for '.$frame_name;
1347 } elseif (!isset($source_data_array[
'description'])) {
1348 $this->errors[] =
'[description] not specified for '.$frame_name;
1349 } elseif (in_array($frame_name.$source_data_array[
'language'].$source_data_array[
'description'], $PreviousFrames)) {
1350 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Language + Description ('.$source_data_array[
'language'].
' + '.$source_data_array[
'description'].
')';
1352 $PreviousFrames[] = $frame_name.$source_data_array[
'language'].$source_data_array[
'description'];
1357 if (!isset($source_data_array[
'email'])) {
1358 $this->errors[] =
'[email] not specified for '.$frame_name;
1359 } elseif (in_array($frame_name.$source_data_array[
'email'], $PreviousFrames)) {
1360 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Email ('.$source_data_array[
'email'].
')';
1362 $PreviousFrames[] = $frame_name.$source_data_array[
'email'];
1379 if (in_array($frame_name, $PreviousFrames)) {
1380 $this->errors[] =
'Only one '.$frame_name.
' tag allowed';
1382 $PreviousFrames[] = $frame_name;
1389 if (!isset($source_data_array[
'frameid'])) {
1390 $this->errors[] =
'[frameid] not specified for '.$frame_name;
1391 } elseif (in_array($frame_name.$source_data_array[
'frameid'], $PreviousFrames)) {
1392 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same FrameID ('.$source_data_array[
'frameid'].
')';
1393 } elseif (in_array($source_data_array[
'frameid'], $PreviousFrames)) {
1395 $this->errors[] =
'Cannot specify a '.$frame_name.
' tag to a singleton tag that already exists ('.$source_data_array[
'frameid'].
')';
1397 $PreviousFrames[] = $frame_name.$source_data_array[
'frameid'];
1398 $PreviousFrames[] = $source_data_array[
'frameid'];
1408 if (!isset($source_data_array[
'ownerid'])) {
1409 $this->errors[] =
'[ownerid] not specified for '.$frame_name;
1410 } elseif (!isset($source_data_array[
'data'])) {
1411 $this->errors[] =
'[data] not specified for '.$frame_name;
1412 } elseif (in_array($frame_name.$source_data_array[
'ownerid'].$source_data_array[
'data'], $PreviousFrames)) {
1413 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same OwnerID + Data ('.$source_data_array[
'ownerid'].
' + '.$source_data_array[
'data'].
')';
1415 $PreviousFrames[] = $frame_name.$source_data_array[
'ownerid'].$source_data_array[
'data'];
1420 if (($frame_name{0} !=
'T') && ($frame_name{0} !=
'W')) {
1421 $this->errors[] =
'Frame not allowed in ID3v2.'.$this->majorversion.
': '.$frame_name;
1426 } elseif ($this->majorversion == 2) {
1428 switch ($frame_name) {
1432 if (!isset($source_data_array[
'ownerid'])) {
1433 $this->errors[] =
'[ownerid] not specified for '.$frame_name;
1434 } elseif (in_array($frame_name.$source_data_array[
'ownerid'], $PreviousFrames)) {
1435 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same OwnerID ('.$source_data_array[
'ownerid'].
')';
1437 $PreviousFrames[] = $frame_name.$source_data_array[
'ownerid'];
1445 if (!isset($source_data_array[
'description'])) {
1446 $this->errors[] =
'[description] not specified for '.$frame_name;
1447 } elseif (in_array($frame_name.$source_data_array[
'description'], $PreviousFrames)) {
1448 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Description ('.$source_data_array[
'description'].
')';
1450 $PreviousFrames[] = $frame_name.$source_data_array[
'description'];
1457 if (!isset($source_data_array[
'language'])) {
1458 $this->errors[] =
'[language] not specified for '.$frame_name;
1459 } elseif (!isset($source_data_array[
'description'])) {
1460 $this->errors[] =
'[description] not specified for '.$frame_name;
1461 } elseif (in_array($frame_name.$source_data_array[
'language'].$source_data_array[
'description'], $PreviousFrames)) {
1462 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Language + Description ('.$source_data_array[
'language'].
' + '.$source_data_array[
'description'].
')';
1464 $PreviousFrames[] = $frame_name.$source_data_array[
'language'].$source_data_array[
'description'];
1469 if (!isset($source_data_array[
'email'])) {
1470 $this->errors[] =
'[email] not specified for '.$frame_name;
1471 } elseif (in_array($frame_name.$source_data_array[
'email'], $PreviousFrames)) {
1472 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same Email ('.$source_data_array[
'email'].
')';
1474 $PreviousFrames[] = $frame_name.$source_data_array[
'email'];
1488 if (in_array($frame_name, $PreviousFrames)) {
1489 $this->errors[] =
'Only one '.$frame_name.
' tag allowed';
1491 $PreviousFrames[] = $frame_name;
1498 if (!isset($source_data_array[
'frameid'])) {
1499 $this->errors[] =
'[frameid] not specified for '.$frame_name;
1500 } elseif (in_array($frame_name.$source_data_array[
'frameid'], $PreviousFrames)) {
1501 $this->errors[] =
'Only one '.$frame_name.
' tag allowed with the same FrameID ('.$source_data_array[
'frameid'].
')';
1502 } elseif (in_array($source_data_array[
'frameid'], $PreviousFrames)) {
1504 $this->errors[] =
'Cannot specify a '.$frame_name.
' tag to a singleton tag that already exists ('.$source_data_array[
'frameid'].
')';
1506 $PreviousFrames[] = $frame_name.$source_data_array[
'frameid'];
1507 $PreviousFrames[] = $source_data_array[
'frameid'];
1512 if (($frame_name{0} !=
'T') && ($frame_name{0} !=
'W')) {
1513 $this->errors[] =
'Frame not allowed in ID3v2.'.$this->majorversion.
': '.$frame_name;
1519 if (!empty($this->errors)) {
1529 if (is_array($this->tag_data)) {
1530 foreach ($this->tag_data as $frame_name => $frame_rawinputdata) {
1531 foreach ($frame_rawinputdata as $irrelevantindex => $source_data_array) {
1533 unset($frame_length);
1534 unset($frame_flags);
1535 $frame_data =
false;
1538 $FrameUnsynchronisation =
false;
1539 if ($this->majorversion >= 4) {
1541 $unsynchdata = $frame_data;
1542 if ($this->id3v2_use_unsynchronisation) {
1545 if (strlen($unsynchdata) != strlen($frame_data)) {
1547 $FrameUnsynchronisation =
true;
1548 $frame_data = $unsynchdata;
1549 if (isset($TagUnsynchronisation) && $TagUnsynchronisation ===
false) {
1552 $TagUnsynchronisation =
true;
1555 if (isset($TagUnsynchronisation)) {
1556 $TagUnsynchronisation =
false;
1559 unset($unsynchdata);
1568 $this->errors[] =
'Frame "'.$frame_name.
'" is NOT allowed';
1570 if ($frame_data ===
false) {
1571 $this->errors[] =
'$this->GenerateID3v2FrameData() failed for "'.$frame_name.
'"';
1572 if ($noerrorsonly) {
1580 $this->warnings[] =
'Ignoring invalid ID3v2 frame type: "'.$frame_name.
'"';
1582 unset($frame_length);
1583 unset($frame_flags);
1586 if (isset($frame_name) && isset($frame_length) && isset($frame_flags) && isset($frame_data)) {
1587 $tagstring .= $frame_name.$frame_length.$frame_flags.$frame_data;
1592 if (!isset($TagUnsynchronisation)) {
1593 $TagUnsynchronisation =
false;
1595 if (($this->majorversion <= 3) && $this->id3v2_use_unsynchronisation) {
1598 if (strlen($unsynchdata) != strlen($tagstring)) {
1600 $TagUnsynchronisation =
true;
1601 $tagstring = $unsynchdata;
1606 $this->paddedlength += 1024;
1615 if ($this->id3v2_use_unsynchronisation && (substr($tagstring, strlen($tagstring) - 1, 1) ==
"\xFF")) {
1618 $TagUnsynchronisation =
true;
1619 $tagstring .=
"\x00";
1623 $tagheader .= chr($this->majorversion);
1624 $tagheader .= chr($this->minorversion);
1628 return $tagheader.$tagstring;
1630 $this->errors[] =
'tag_data is not an array in GenerateID3v2Tag()';
1637 } elseif (!$this->IsANumber(substr($pricestring, 3),
true)) {
1645 switch ($framename) {
1657 switch ($framename) {
1669 if (($eventid < 0) || ($eventid > 0xFF)) {
1672 } elseif (($eventid >= 0xF0) && ($eventid <= 0xFC)) {
1675 } elseif (($eventid >= 0x17) && ($eventid <= 0xDF)) {
1678 } elseif (($eventid >= 0x0E) && ($eventid <= 0x16) && ($this->majorversion == 2)) {
1681 } elseif (($eventid >= 0x15) && ($eventid <= 0x16) && ($this->majorversion == 3)) {
1689 if (($contenttype >= 0) && ($contenttype <= 8) && ($this->majorversion == 4)) {
1691 } elseif (($contenttype >= 0) && ($contenttype <= 6) && ($this->majorversion == 3)) {
1698 if (($channeltype >= 0) && ($channeltype <= 8) && ($this->majorversion == 4)) {
1705 if (($picturetype >= 0) && ($picturetype <= 0x14) && ($this->majorversion >= 2) && ($this->majorversion <= 4)) {
1712 if ($imageformat ==
'-->') {
1714 } elseif ($this->majorversion == 2) {
1715 if ((strlen($imageformat) == 3) && ($imageformat == strtoupper($imageformat))) {
1718 } elseif (($this->majorversion == 3) || ($this->majorversion == 4)) {
1727 if (($this->majorversion >= 3) && ($receivedas >= 0) && ($receivedas <= 8)) {
1734 if (($RGADname >= 0) && ($RGADname <= 2)) {
1741 if (($RGADoriginator >= 0) && ($RGADoriginator <= 3)) {
1748 static $ID3v2IsValidTextEncoding_cache = array(
1749 2 => array(
true,
true),
1750 3 => array(
true,
true),
1751 4 => array(
true,
true,
true,
true));
1752 return isset($ID3v2IsValidTextEncoding_cache[$this->majorversion][$textencodingbyte]);
1768 $data = str_replace(
"\xFF\x00",
"\xFF\x00\x00", $data);
1769 $unsyncheddata =
'';
1770 $datalength = strlen($data);
1771 for ($i = 0; $i < $datalength; $i++) {
1772 $thischar = $data{$i};
1773 $unsyncheddata .= $thischar;
1774 if ($thischar ==
"\xFF") {
1775 $nextchar = ord($data{$i + 1});
1776 if (($nextchar & 0xE0) == 0xE0) {
1778 $unsyncheddata .=
"\x00";
1782 return $unsyncheddata;
1788 if (is_array($var)) {
1789 $keys = array_keys($var);
1791 for ($i = 0; $i < count($keys); $i++) {
1792 if (is_string($keys[$i])) {
1803 if (is_array($arr1) && is_array($arr2)) {
1805 $new_array = array();
1809 $keys = array_merge(array_keys($arr1), array_keys($arr2));
1810 foreach ($keys as $key) {
1815 $new_array = array_reverse(array_unique(array_reverse(array_merge($arr1, $arr2))));
1820 return $arr2 ? $arr2 : $arr1;
1825 if ((strlen($mimestring) >= 3) && (strpos($mimestring,
'/') > 0) && (strpos($mimestring,
'/') < (strlen($mimestring) - 1))) {
1833 if (($number > (0 - pow(2, $maxbits - 1))) && ($number <= pow(2, $maxbits - 1))) {
1837 if (($number >= 0) && ($number <= pow(2, $maxbits))) {
1845 $parts = @parse_url($url);
1846 $parts[
'scheme'] = (isset($parts[
'scheme']) ? $parts[
'scheme'] :
'');
1847 $parts[
'host'] = (isset($parts[
'host']) ? $parts[
'host'] :
'');
1848 $parts[
'user'] = (isset($parts[
'user']) ? $parts[
'user'] :
'');
1849 $parts[
'pass'] = (isset($parts[
'pass']) ? $parts[
'pass'] :
'');
1850 $parts[
'path'] = (isset($parts[
'path']) ? $parts[
'path'] :
'');
1851 $parts[
'query'] = (isset($parts[
'query']) ? $parts[
'query'] :
'');
1859 if ($allowUserPass !==
true) {
1860 if (strstr($url,
'@')) {
1867 if (($parts[
'scheme'] !=
'http') && ($parts[
'scheme'] !=
'https') && ($parts[
'scheme'] !=
'ftp') && ($parts[
'scheme'] !=
'gopher')) {
1869 } elseif (!eregi(
"^[[:alnum:]]([-.]?[0-9a-z])*\.[a-z]{2,3}$", $parts[
'host'], $regs) && !IsValidDottedIP($parts[
'host'])) {
1871 } elseif (!eregi(
"^([[:alnum:]-]|[\_])*$", $parts[
'user'], $regs)) {
1873 } elseif (!eregi(
"^([[:alnum:]-]|[\_])*$", $parts[
'pass'], $regs)) {
1875 } elseif (!eregi(
"^[[:alnum:]/_\.@~-]*$", $parts[
'path'], $regs)) {
1877 } elseif (!eregi(
"^[[:alnum:]?&=+:;_()%#/,\.-]*$", $parts[
'query'], $regs)) {
1887 $long_description = str_replace(
' ',
'_', strtolower(trim($long_description)));
1888 static $ID3v2ShortFrameNameLookup = array();
1889 if (empty($ID3v2ShortFrameNameLookup)) {
1892 $ID3v2ShortFrameNameLookup[2][
'comment'] =
'COM';
1893 $ID3v2ShortFrameNameLookup[2][
'album'] =
'TAL';
1894 $ID3v2ShortFrameNameLookup[2][
'beats_per_minute'] =
'TBP';
1895 $ID3v2ShortFrameNameLookup[2][
'composer'] =
'TCM';
1896 $ID3v2ShortFrameNameLookup[2][
'genre'] =
'TCO';
1897 $ID3v2ShortFrameNameLookup[2][
'copyright'] =
'TCR';
1898 $ID3v2ShortFrameNameLookup[2][
'encoded_by'] =
'TEN';
1899 $ID3v2ShortFrameNameLookup[2][
'language'] =
'TLA';
1900 $ID3v2ShortFrameNameLookup[2][
'length'] =
'TLE';
1901 $ID3v2ShortFrameNameLookup[2][
'original_artist'] =
'TOA';
1902 $ID3v2ShortFrameNameLookup[2][
'original_filename'] =
'TOF';
1903 $ID3v2ShortFrameNameLookup[2][
'original_lyricist'] =
'TOL';
1904 $ID3v2ShortFrameNameLookup[2][
'original_album_title'] =
'TOT';
1905 $ID3v2ShortFrameNameLookup[2][
'artist'] =
'TP1';
1906 $ID3v2ShortFrameNameLookup[2][
'band'] =
'TP2';
1907 $ID3v2ShortFrameNameLookup[2][
'conductor'] =
'TP3';
1908 $ID3v2ShortFrameNameLookup[2][
'remixer'] =
'TP4';
1909 $ID3v2ShortFrameNameLookup[2][
'publisher'] =
'TPB';
1910 $ID3v2ShortFrameNameLookup[2][
'isrc'] =
'TRC';
1911 $ID3v2ShortFrameNameLookup[2][
'tracknumber'] =
'TRK';
1912 $ID3v2ShortFrameNameLookup[2][
'size'] =
'TSI';
1913 $ID3v2ShortFrameNameLookup[2][
'encoder_settings'] =
'TSS';
1914 $ID3v2ShortFrameNameLookup[2][
'description'] =
'TT1';
1915 $ID3v2ShortFrameNameLookup[2][
'title'] =
'TT2';
1916 $ID3v2ShortFrameNameLookup[2][
'subtitle'] =
'TT3';
1917 $ID3v2ShortFrameNameLookup[2][
'lyricist'] =
'TXT';
1918 $ID3v2ShortFrameNameLookup[2][
'user_text'] =
'TXX';
1919 $ID3v2ShortFrameNameLookup[2][
'year'] =
'TYE';
1920 $ID3v2ShortFrameNameLookup[2][
'unique_file_identifier'] =
'UFI';
1921 $ID3v2ShortFrameNameLookup[2][
'unsynchronised_lyrics'] =
'ULT';
1922 $ID3v2ShortFrameNameLookup[2][
'url_file'] =
'WAF';
1923 $ID3v2ShortFrameNameLookup[2][
'url_artist'] =
'WAR';
1924 $ID3v2ShortFrameNameLookup[2][
'url_source'] =
'WAS';
1925 $ID3v2ShortFrameNameLookup[2][
'copyright_information'] =
'WCP';
1926 $ID3v2ShortFrameNameLookup[2][
'url_publisher'] =
'WPB';
1927 $ID3v2ShortFrameNameLookup[2][
'url_user'] =
'WXX';
1930 $ID3v2ShortFrameNameLookup[3][
'audio_encryption'] =
'AENC';
1931 $ID3v2ShortFrameNameLookup[3][
'attached_picture'] =
'APIC';
1932 $ID3v2ShortFrameNameLookup[3][
'comment'] =
'COMM';
1933 $ID3v2ShortFrameNameLookup[3][
'commercial'] =
'COMR';
1934 $ID3v2ShortFrameNameLookup[3][
'encryption_method_registration'] =
'ENCR';
1935 $ID3v2ShortFrameNameLookup[3][
'event_timing_codes'] =
'ETCO';
1936 $ID3v2ShortFrameNameLookup[3][
'general_encapsulated_object'] =
'GEOB';
1937 $ID3v2ShortFrameNameLookup[3][
'group_identification_registration'] =
'GRID';
1938 $ID3v2ShortFrameNameLookup[3][
'linked_information'] =
'LINK';
1939 $ID3v2ShortFrameNameLookup[3][
'music_cd_identifier'] =
'MCDI';
1940 $ID3v2ShortFrameNameLookup[3][
'mpeg_location_lookup_table'] =
'MLLT';
1941 $ID3v2ShortFrameNameLookup[3][
'ownership'] =
'OWNE';
1942 $ID3v2ShortFrameNameLookup[3][
'play_counter'] =
'PCNT';
1943 $ID3v2ShortFrameNameLookup[3][
'popularimeter'] =
'POPM';
1944 $ID3v2ShortFrameNameLookup[3][
'position_synchronisation'] =
'POSS';
1945 $ID3v2ShortFrameNameLookup[3][
'private'] =
'PRIV';
1946 $ID3v2ShortFrameNameLookup[3][
'recommended_buffer_size'] =
'RBUF';
1947 $ID3v2ShortFrameNameLookup[3][
'reverb'] =
'RVRB';
1948 $ID3v2ShortFrameNameLookup[3][
'synchronised_lyrics'] =
'SYLT';
1949 $ID3v2ShortFrameNameLookup[3][
'synchronised_tempo_codes'] =
'SYTC';
1950 $ID3v2ShortFrameNameLookup[3][
'album'] =
'TALB';
1951 $ID3v2ShortFrameNameLookup[3][
'beats_per_minute'] =
'TBPM';
1952 $ID3v2ShortFrameNameLookup[3][
'composer'] =
'TCOM';
1953 $ID3v2ShortFrameNameLookup[3][
'genre'] =
'TCON';
1954 $ID3v2ShortFrameNameLookup[3][
'copyright'] =
'TCOP';
1955 $ID3v2ShortFrameNameLookup[3][
'playlist_delay'] =
'TDLY';
1956 $ID3v2ShortFrameNameLookup[3][
'encoded_by'] =
'TENC';
1957 $ID3v2ShortFrameNameLookup[3][
'lyricist'] =
'TEXT';
1958 $ID3v2ShortFrameNameLookup[3][
'file_type'] =
'TFLT';
1959 $ID3v2ShortFrameNameLookup[3][
'content_group_description'] =
'TIT1';
1960 $ID3v2ShortFrameNameLookup[3][
'title'] =
'TIT2';
1961 $ID3v2ShortFrameNameLookup[3][
'subtitle'] =
'TIT3';
1962 $ID3v2ShortFrameNameLookup[3][
'initial_key'] =
'TKEY';
1963 $ID3v2ShortFrameNameLookup[3][
'language'] =
'TLAN';
1964 $ID3v2ShortFrameNameLookup[3][
'length'] =
'TLEN';
1965 $ID3v2ShortFrameNameLookup[3][
'media_type'] =
'TMED';
1966 $ID3v2ShortFrameNameLookup[3][
'original_album_title'] =
'TOAL';
1967 $ID3v2ShortFrameNameLookup[3][
'original_filename'] =
'TOFN';
1968 $ID3v2ShortFrameNameLookup[3][
'original_lyricist'] =
'TOLY';
1969 $ID3v2ShortFrameNameLookup[3][
'original_artist'] =
'TOPE';
1970 $ID3v2ShortFrameNameLookup[3][
'file_owner'] =
'TOWN';
1971 $ID3v2ShortFrameNameLookup[3][
'artist'] =
'TPE1';
1972 $ID3v2ShortFrameNameLookup[3][
'band'] =
'TPE2';
1973 $ID3v2ShortFrameNameLookup[3][
'conductor'] =
'TPE3';
1974 $ID3v2ShortFrameNameLookup[3][
'remixer'] =
'TPE4';
1975 $ID3v2ShortFrameNameLookup[3][
'part_of_set'] =
'TPOS';
1976 $ID3v2ShortFrameNameLookup[3][
'publisher'] =
'TPUB';
1977 $ID3v2ShortFrameNameLookup[3][
'tracknumber'] =
'TRCK';
1978 $ID3v2ShortFrameNameLookup[3][
'internet_radio_station_name'] =
'TRSN';
1979 $ID3v2ShortFrameNameLookup[3][
'internet_radio_station_owner'] =
'TRSO';
1980 $ID3v2ShortFrameNameLookup[3][
'isrc'] =
'TSRC';
1981 $ID3v2ShortFrameNameLookup[3][
'encoder_settings'] =
'TSSE';
1982 $ID3v2ShortFrameNameLookup[3][
'user_text'] =
'TXXX';
1983 $ID3v2ShortFrameNameLookup[3][
'unique_file_identifier'] =
'UFID';
1984 $ID3v2ShortFrameNameLookup[3][
'terms_of_use'] =
'USER';
1985 $ID3v2ShortFrameNameLookup[3][
'unsynchronised_lyrics'] =
'USLT';
1986 $ID3v2ShortFrameNameLookup[3][
'commercial'] =
'WCOM';
1987 $ID3v2ShortFrameNameLookup[3][
'copyright_information'] =
'WCOP';
1988 $ID3v2ShortFrameNameLookup[3][
'url_file'] =
'WOAF';
1989 $ID3v2ShortFrameNameLookup[3][
'url_artist'] =
'WOAR';
1990 $ID3v2ShortFrameNameLookup[3][
'url_source'] =
'WOAS';
1991 $ID3v2ShortFrameNameLookup[3][
'url_station'] =
'WORS';
1992 $ID3v2ShortFrameNameLookup[3][
'payment'] =
'WPAY';
1993 $ID3v2ShortFrameNameLookup[3][
'url_publisher'] =
'WPUB';
1994 $ID3v2ShortFrameNameLookup[3][
'url_user'] =
'WXXX';
1998 $ID3v2ShortFrameNameLookup[4] = $ID3v2ShortFrameNameLookup[3];
2001 $ID3v2ShortFrameNameLookup[3][
'equalisation'] =
'EQUA';
2002 $ID3v2ShortFrameNameLookup[3][
'involved_people_list'] =
'IPLS';
2003 $ID3v2ShortFrameNameLookup[3][
'relative_volume_adjustment'] =
'RVAD';
2004 $ID3v2ShortFrameNameLookup[3][
'date'] =
'TDAT';
2005 $ID3v2ShortFrameNameLookup[3][
'time'] =
'TIME';
2006 $ID3v2ShortFrameNameLookup[3][
'original_release_year'] =
'TORY';
2007 $ID3v2ShortFrameNameLookup[3][
'recording_dates'] =
'TRDA';
2008 $ID3v2ShortFrameNameLookup[3][
'size'] =
'TSIZ';
2009 $ID3v2ShortFrameNameLookup[3][
'year'] =
'TYER';
2013 $ID3v2ShortFrameNameLookup[4][
'audio_seek_point_index'] =
'ASPI';
2014 $ID3v2ShortFrameNameLookup[4][
'equalisation'] =
'EQU2';
2015 $ID3v2ShortFrameNameLookup[4][
'relative_volume_adjustment'] =
'RVA2';
2016 $ID3v2ShortFrameNameLookup[4][
'seek'] =
'SEEK';
2017 $ID3v2ShortFrameNameLookup[4][
'signature'] =
'SIGN';
2018 $ID3v2ShortFrameNameLookup[4][
'encoding_time'] =
'TDEN';
2019 $ID3v2ShortFrameNameLookup[4][
'original_release_time'] =
'TDOR';
2020 $ID3v2ShortFrameNameLookup[4][
'recording_time'] =
'TDRC';
2021 $ID3v2ShortFrameNameLookup[4][
'release_time'] =
'TDRL';
2022 $ID3v2ShortFrameNameLookup[4][
'tagging_time'] =
'TDTG';
2023 $ID3v2ShortFrameNameLookup[4][
'involved_people_list'] =
'TIPL';
2024 $ID3v2ShortFrameNameLookup[4][
'musician_credits_list'] =
'TMCL';
2025 $ID3v2ShortFrameNameLookup[4][
'mood'] =
'TMOO';
2026 $ID3v2ShortFrameNameLookup[4][
'produced_notice'] =
'TPRO';
2027 $ID3v2ShortFrameNameLookup[4][
'album_sort_order'] =
'TSOA';
2028 $ID3v2ShortFrameNameLookup[4][
'performer_sort_order'] =
'TSOP';
2029 $ID3v2ShortFrameNameLookup[4][
'title_sort_order'] =
'TSOT';
2030 $ID3v2ShortFrameNameLookup[4][
'set_subtitle'] =
'TSST';
2032 return @$ID3v2ShortFrameNameLookup[
$majorversion][strtolower($long_description)];